mirror of
https://github.com/inspec/inspec
synced 2024-11-26 14:40:26 +00:00
add feature to fetch children from registry key
This commit is contained in:
parent
1faa68732e
commit
57bdd3464c
5 changed files with 106 additions and 17 deletions
|
@ -24,9 +24,31 @@ require 'json'
|
|||
# }) do
|
||||
# its('Start') { should eq 2 }
|
||||
# end
|
||||
#
|
||||
# Get all childs of a registry key:
|
||||
# describe registry_key('Task Scheduler','HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet').children do
|
||||
# it { should_not eq [] }
|
||||
# end
|
||||
#
|
||||
# Example to use regular expressions for keys
|
||||
# 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
|
||||
# }
|
||||
#
|
||||
# Example to use regular expressions 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
|
||||
|
||||
module Inspec::Resources
|
||||
class RegistryKey < Inspec.resource(1)
|
||||
class RegistryKey < Inspec.resource(1) # rubocop:disable Metrics/ClassLength
|
||||
name 'registry_key'
|
||||
desc 'Use the registry_key InSpec audit resource to test key values in the Microsoft Windows registry.'
|
||||
example "
|
||||
|
@ -42,7 +64,9 @@ module Inspec::Resources
|
|||
if reg_key && reg_key.is_a?(Hash)
|
||||
@options = @options.merge!(reg_key)
|
||||
# generate registry_key if we do not have a regular expression
|
||||
@options[:path] = @options[:hive] + '\\' + @options[:key]
|
||||
@options[:path] = @options[:hive]
|
||||
# add optional key path
|
||||
@options[:path] += '\\' + @options[:key] if @options[:key]
|
||||
@options[:name] ||= @options[:path]
|
||||
else
|
||||
@options[:name] = name
|
||||
|
@ -77,6 +101,11 @@ module Inspec::Resources
|
|||
!val.nil? && registry_property_value(val, property_name) == value && (property_type.nil? || registry_property_type(val, property_name) == map2type(property_type)) ? true : false
|
||||
end
|
||||
|
||||
# returns an arrray of child nodes
|
||||
def children(filter = nil)
|
||||
children_keys(@options[:path], filter)
|
||||
end
|
||||
|
||||
# returns nil, if not existant or value
|
||||
def method_missing(meth)
|
||||
# get data
|
||||
|
@ -88,7 +117,7 @@ module Inspec::Resources
|
|||
"Registry Key #{@options[:name]}"
|
||||
end
|
||||
|
||||
# private
|
||||
private
|
||||
|
||||
def prep_prop(property)
|
||||
property.to_s.downcase
|
||||
|
@ -114,15 +143,10 @@ module Inspec::Resources
|
|||
|
||||
def registry_key(path)
|
||||
return @registry_cache if defined?(@registry_cache)
|
||||
|
||||
# load registry key and all properties
|
||||
script = <<-EOH
|
||||
$path = '#{path}'
|
||||
Function Get-InSpec-RegistryKey($path) {
|
||||
$fullpath = 'Registry::' + $path
|
||||
$reg = Get-Item $fullpath
|
||||
|
||||
# convert properties
|
||||
Function InSpec-GetRegistryKey($path) {
|
||||
$reg = Get-Item ('Registry::' + $path)
|
||||
$properties = New-Object -Type PSObject
|
||||
$reg.Property | ForEach-Object {
|
||||
$key = $_
|
||||
|
@ -131,15 +155,15 @@ module Inspec::Resources
|
|||
"value" = $reg.GetValue($key);
|
||||
"type" = $reg.GetValueKind($key);
|
||||
}
|
||||
$properties | Add-Member –MemberType NoteProperty –Name $_ –Value $value
|
||||
$properties | Add-Member NoteProperty $_ $value
|
||||
}
|
||||
$properties
|
||||
}
|
||||
Get-InSpec-RegistryKey($path) | ConvertTo-Json
|
||||
$path = '#{path}'
|
||||
InSpec-GetRegistryKey($path) | ConvertTo-Json
|
||||
EOH
|
||||
|
||||
cmd = inspec.powershell(script)
|
||||
|
||||
# cannot rely on exit code for now, successful command returns exit code 1
|
||||
# return nil if cmd.exit_status != 0, try to parse json
|
||||
begin
|
||||
|
@ -151,10 +175,38 @@ module Inspec::Resources
|
|||
rescue JSON::ParserError => _e
|
||||
@registry_cache = nil
|
||||
end
|
||||
|
||||
@registry_cache
|
||||
end
|
||||
|
||||
def children_keys(path, filter = '')
|
||||
return @children_cache if defined?(@children_cache)
|
||||
filter = filter.source if filter.is_a? ::Regexp
|
||||
script = <<-EOH
|
||||
Function InSpec-FindChildsRegistryKeys($path, $filter) {
|
||||
# get information about the child registry keys
|
||||
$items = Get-ChildItem -Path ('Registry::' + $path) -rec -ea SilentlyContinue
|
||||
# filter entries
|
||||
$items | Where-Object {
|
||||
$name = $_.Name
|
||||
$simple = $name -replace "HKEY_LOCAL_MACHINE\\\\",""
|
||||
$simple = $name -replace "HKEY_USERS\\\\",""
|
||||
$simple -Match $filter
|
||||
} | % { $_.Name }
|
||||
}
|
||||
|
||||
$path = '#{path}'
|
||||
$filter = "#{filter}"
|
||||
ConvertTo-Json @(InSpec-FindChildsRegistryKeys $path $filter)
|
||||
EOH
|
||||
cmd = inspec.powershell(script)
|
||||
begin
|
||||
@children_cache = JSON.parse(cmd.stdout)
|
||||
rescue JSON::ParserError => _e
|
||||
@children_cache = []
|
||||
end
|
||||
@children_cache
|
||||
end
|
||||
|
||||
# Registry key value types
|
||||
# @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms724884(v=vs.85).aspx
|
||||
# REG_NONE 0
|
||||
|
|
|
@ -10,3 +10,4 @@ depends 'yum'
|
|||
depends 'runit'
|
||||
depends 'postgresql'
|
||||
depends 'httpd', '~> 0.2'
|
||||
depends 'windows'
|
||||
|
|
|
@ -71,4 +71,17 @@ if node['platform_family'] == 'windows'
|
|||
recursive true
|
||||
action :create
|
||||
end
|
||||
|
||||
# used to verify pattern test
|
||||
::Chef::Recipe.send(:include, Chef::Mixin::PowershellOut)
|
||||
cmd = powershell_out!('Get-WmiObject -Class Win32_UserAccount | % { $_.SID } | ConvertTo-Json')
|
||||
sids = JSON.parse(cmd.stdout)
|
||||
sids.each { |sid|
|
||||
registry_key "HKEY_USERS\\#{sid}\\Software\\Policies\\Microsoft\\Windows\\Installer" do
|
||||
values [{ name: 'AlwaysInstallElevated', type: :dword, data: 0 }]
|
||||
recursive true
|
||||
ignore_failure true # ignore users that have not been logged in
|
||||
action :create
|
||||
end
|
||||
}
|
||||
end
|
||||
|
|
|
@ -145,8 +145,8 @@ class MockLoader
|
|||
'env' => cmd.call('env'),
|
||||
'${Env:PATH}' => cmd.call('$env-PATH'),
|
||||
# registry key test (winrm 1.6.0, 1.6.1)
|
||||
'2790db1e88204a073ed7fd3493f5445e5ce531afd0d2724a0e36c17110c535e6' => cmd.call('reg_schedule'),
|
||||
'25a1a38fafc289a646d30f7aa966ce0901c267798f47abf2f9440e27d31a5b7d' => cmd.call('reg_schedule'),
|
||||
'dd429dd12596fa193ba4111469b4417ecbd78a1d7ba4317c334c9111644bae44' => cmd.call('reg_schedule'),
|
||||
'Fdd429dd12596fa193ba4111469b4417ecbd78a1d7ba4317c334c9111644bae44' => cmd.call('reg_schedule'),
|
||||
'Auditpol /get /subcategory:\'User Account Management\' /r' => cmd.call('auditpol'),
|
||||
'/sbin/auditctl -l' => cmd.call('auditctl'),
|
||||
'/sbin/auditctl -s' => cmd.call('auditctl-s'),
|
||||
|
|
|
@ -66,7 +66,6 @@ describe registry_key('HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Serv
|
|||
end
|
||||
|
||||
# test option hash
|
||||
|
||||
describe registry_key({
|
||||
hive: 'HKLM',
|
||||
key: 'SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services'
|
||||
|
@ -81,3 +80,27 @@ describe registry_key({
|
|||
}) do
|
||||
it { should exist }
|
||||
end
|
||||
|
||||
# test regular expressions in our match
|
||||
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
|
||||
|
||||
# verify all children via a regular expression
|
||||
control 'regex-test' do
|
||||
title "Ensure 'Always install with elevated privileges' is set to 'Disabled'"
|
||||
children = registry_key({
|
||||
hive: 'HKEY_USERS'
|
||||
}).children(/^S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]{3,}\\Software\\Policies\\Microsoft\\Windows\\Installer/)
|
||||
describe children do
|
||||
it { should_not eq []}
|
||||
end
|
||||
children.each { |key|
|
||||
describe registry_key(key) do
|
||||
its('AlwaysInstallElevated') { should cmp 0 }
|
||||
end
|
||||
}
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue