diff --git a/lib/resources/registry_key.rb b/lib/resources/registry_key.rb index 1b71ffcaa..6ba1b7207 100644 --- a/lib/resources/registry_key.rb +++ b/lib/resources/registry_key.rb @@ -23,37 +23,36 @@ class RegistryKey < Inspec.resource(1) end def exists? - !registry_value(@reg_key).nil? + !registry_key(@reg_key).nil? end def has_value?(value) - val = registry_value(@reg_key) - !val.nil? && val['(default)'.to_s]['value'] == value ? true : false + val = registry_key(@reg_key) + !val.nil? && registry_property_value(val, '(default)') == value ? true : false end def has_property?(property_name, property_type = nil) - val = registry_value(@reg_key) - !val.nil? && !val[property_name.to_s].nil? && (property_type.nil? || val[property_name.to_s]['type'] == map2type(property_type)) ? true : false + val = registry_key(@reg_key) + !val.nil? && registry_property_exists(val, property_name) && (property_type.nil? || registry_property_type(val, property_name) == map2type(property_type)) ? true : false end # deactivate rubocop, because we need to stay compatible with Serverspe # rubocop:disable Style/OptionalArguments def has_property_value?(property_name, property_type = nil, value) # rubocop:enable Style/OptionalArguments - val = registry_value(@reg_key) + val = registry_key(@reg_key) # convert value to binary if required value = value.bytes if !property_type.nil? && map2type(property_type) == 3 && !value.is_a?(Array) - !val.nil? && val[property_name.to_s]['value'] == value && (property_type.nil? || val[property_name.to_s]['type'] == map2type(property_type)) ? true : false + !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 nil, if not existant or value def method_missing(meth) # get data - val = registry_value(@reg_key) - return nil if val.nil? - val[meth.to_s]['value'] + val = registry_key(@reg_key) + registry_property_value(val, meth) end def to_s @@ -62,7 +61,25 @@ class RegistryKey < Inspec.resource(1) private - def registry_value(path) + def registry_property_exists(regkey, property) + return false if regkey.nil? || property.nil? + # always ensure the key is lower case + !regkey[property.to_s.downcase].nil? + end + + def registry_property_value(regkey, property) + return nil if regkey.nil? || property.nil? + # always ensure the key is lower case + regkey[property.to_s.downcase]['value'] + end + + def registry_property_type(regkey, property) + return nil if regkey.nil? || property.nil? + # always ensure the key is lower case + regkey[property.to_s.downcase]['type'] + end + + def registry_key(path) return @registy_cache if defined?(@registy_cache) # load registry key and all properties @@ -87,6 +104,10 @@ class RegistryKey < Inspec.resource(1) # return nil if cmd.exit_status != 0, try to parse json begin @registy_cache = JSON.parse(cmd.stdout) + # convert keys to lower case + @registy_cache = Hash[@registy_cache.map do |key, value| + [key.downcase, value] + end] rescue JSON::ParserError => _e @registy_cache = nil end diff --git a/test/integration/cookbooks/os_prepare/recipes/registry_key.rb b/test/integration/cookbooks/os_prepare/recipes/registry_key.rb index ee10d9e0f..17c4de852 100644 --- a/test/integration/cookbooks/os_prepare/recipes/registry_key.rb +++ b/test/integration/cookbooks/os_prepare/recipes/registry_key.rb @@ -66,4 +66,9 @@ if node['platform_family'] == 'windows' action :create end + registry_key 'HKLM\System\CurrentControlSet\Control\Lsa\MSV1_0' do + values [{ name: 'NTLMMinServerSec', type: :dword, data: 537_395_200 }] + recursive true + action :create + end end diff --git a/test/integration/test/integration/default/registry_key_spec.rb b/test/integration/test/integration/default/registry_key_spec.rb index 484331b0a..8ca789926 100644 --- a/test/integration/test/integration/default/registry_key_spec.rb +++ b/test/integration/test/integration/default/registry_key_spec.rb @@ -6,11 +6,16 @@ if os.windows? it { should exist } it { should have_value('test') } it { should have_property('binary value', :binary) } + it { should have_property('Binary value', :binary) } it { should have_property('string value') } + it { should have_property('String value') } it { should have_property('dword value', :dword) } it { should have_property_value('multistring value', :multi_string, ['test', 'multi','string','data']) } + it { should have_property_value('Multistring Value', :multi_string, ['test', 'multi','string','data']) } it { should have_property_value('qword value', :qword, 0) } + it { should have_property_value('Qword value', :qword, 0) } it { should have_property_value('binary value', :binary, 'dfa0f066') } + it { should have_property_value('Binary value', :binary, 'dfa0f066') } end # serverspec compatability @@ -33,6 +38,8 @@ if os.windows? describe registry_key('HKLM\System\CurrentControlSet\Control\Session Manager') do it { should exist } it { should_not have_property_value('SafeDllSearchMode', :type_dword, 0) } + # case-insensitive test + it { should_not have_property_value('safedllsearchmode', :type_dword, 0) } end describe registry_key('HKLM\System\CurrentControlSet\Services\LanManServer\Parameters') do @@ -43,6 +50,8 @@ if os.windows? describe registry_key('HKLM\Software\Policies\Microsoft\Internet Explorer\Main') do it { should exist } its('Isolation64Bit') { should eq 1 } + # check that its is case-insensitive + its('isolation64bit') { should eq 1 } end describe registry_key('HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services') do @@ -50,4 +59,9 @@ if os.windows? its('MinEncryptionLevel') { should eq 3 } end + describe registry_key('HKLM\System\CurrentControlSet\Control\Lsa\MSV1_0') do + it { should exist } + its('NTLMMinServerSec') { should eq 537_395_200 } + its('NtlmMinServerSec') { should eq 537_395_200 } + end end