class Inspec::Resources::RegistryKey

Public Class Methods

new(name, reg_key = nil) click to toggle source
# File lib/inspec/resources/registry_key.rb, line 59
def initialize(name, reg_key = nil)
  # if we have one parameter, we use it as name
  reg_key ||= name
  @options = {}
  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] = generate_registry_key_path_from_options
    @options[:name] ||= @options[:path]
  else
    @options[:name] = name
    @options[:path] = reg_key
  end

  return skip_resource "The `registry_key` resource is not supported on your OS yet." unless inspec.os.windows?
end

Public Instance Methods

children(filter = nil) click to toggle source

returns an arrray of child nodes

# File lib/inspec/resources/registry_key.rb, line 104
def children(filter = nil)
  children_keys(@options[:path], filter)
end
exists?() click to toggle source
# File lib/inspec/resources/registry_key.rb, line 77
def exists?
  !registry_key(@options[:path]).nil?
end
has_property?(property_name, property_type = nil) click to toggle source
# File lib/inspec/resources/registry_key.rb, line 86
def has_property?(property_name, property_type = nil)
  val = registry_key(@options[:path])
  !val.nil? && registry_property_exists(val, property_name) && (property_type.nil? || registry_property_type(val, property_name) == map2type(property_type)) ? true : false
end
has_property_value?(property_name, property_type = nil, value) click to toggle source

deactivate rubocop, because we need to stay compatible with Serverspe rubocop:disable Style/OptionalArguments

# File lib/inspec/resources/registry_key.rb, line 93
def has_property_value?(property_name, property_type = nil, value)
  # rubocop:enable Style/OptionalArguments
  val = registry_key(@options[:path])

  # convert value to binary if required
  value = value.bytes if !property_type.nil? && map2type(property_type) == 3 && !value.is_a?(Array)

  !val.nil? && registry_property_value(val, property_name) == value && (property_type.nil? || registry_property_type(val, property_name) == map2type(property_type)) ? true : false
end
has_value?(value) click to toggle source
# File lib/inspec/resources/registry_key.rb, line 81
def has_value?(value)
  val = registry_key(@options[:path])
  !val.nil? && registry_property_value(val, "(default)") == value ? true : false
end
method_missing(*keys) click to toggle source

returns nil, if not existent or value

# File lib/inspec/resources/registry_key.rb, line 109
def method_missing(*keys)
  # allow the use of array syntax in an `its` block so that users
  # can use it to query for keys with . characters in them
  if keys.is_a?(Array)
    keys.shift if keys[0] == :[]
    key = keys.first
  else
    key = keys
  end

  # get data
  val = registry_key(@options[:path])
  registry_property_value(val, key)
end
to_s() click to toggle source
# File lib/inspec/resources/registry_key.rb, line 124
def to_s
  "Registry Key #{@options[:name]}"
end

Private Instance Methods

children_keys(path, filter = "") click to toggle source
# File lib/inspec/resources/registry_key.rb, line 204
    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
format_key_from_options() click to toggle source
# File lib/inspec/resources/registry_key.rb, line 280
def format_key_from_options
  key = @options[:key]
  return "" unless key

  key.start_with?("\\") ? key : "\\#{key}"
end
generate_registry_key_path_from_options() click to toggle source
# File lib/inspec/resources/registry_key.rb, line 273
def generate_registry_key_path_from_options
  path = @options[:hive]
  path += format_key_from_options

  path
end
map2type(symbol) click to toggle source

Registry key value types @see msdn.microsoft.com/en-us/library/windows/desktop/ms724884(v=vs.85).aspx REG_NONE 0 REG_SZ 1 REG_EXPAND_SZ 2 REG_BINARY 3 REG_DWORD 4 REG_DWORD_LITTLE_ENDIAN 4 REG_DWORD_BIG_ENDIAN 5 REG_LINK 6 REG_MULTI_SZ 7 REG_RESOURCE_LIST 8 REG_FULL_RESOURCE_DESCRIPTOR 9 REG_RESOURCE_REQUIREMENTS_LIST 10 REG_QWORD 11 REG_QWORD_LITTLE_ENDIAN 11

# File lib/inspec/resources/registry_key.rb, line 250
def map2type(symbol)
  options = {}

  # chef symbols, we prefer those
  options[:binary] = 3
  options[:string] = 1
  options[:multi_string] = 7
  options[:expand_string] = 2
  options[:dword] = 4
  options[:dword_big_endian] = 5
  options[:qword] = 11

  # serverspec symbols
  options[:type_string] = 1
  options[:type_binary] = 3
  options[:type_dword] = 4
  options[:type_qword] = 11
  options[:type_multistring] = 7
  options[:type_expandstring] = 2

  options[symbol]
end
prep_prop(property) click to toggle source
# File lib/inspec/resources/registry_key.rb, line 130
def prep_prop(property)
  property.to_s.downcase
end
registry_key(path) click to toggle source
# File lib/inspec/resources/registry_key.rb, line 155
    def registry_key(path)
      return @registry_cache if defined?(@registry_cache)

      # load registry key and all properties
      script = <<-EOH
      Function InSpec-GetRegistryKey($path) {
        $reg = Get-Item ('Registry::' + $path)
        if ($reg -eq $null) {
          Write-Error "InSpec: Failed to find registry key"
          exit 1001
        }

        $properties = New-Object -Type PSObject
        $reg.Property | ForEach-Object {
            $key = $_
            $keytype = $key
            if ("(default)".Equals($key)) { $keytype = '' }
            $value = New-Object psobject -Property @{
              "value" =  $(Get-ItemProperty ('Registry::' + $path)).$key;
              "type"  = $reg.GetValueKind($keytype);
            }
            $properties | Add-Member NoteProperty $_ $value
        }
        $properties
      }
      $path = '#{path}'
      InSpec-GetRegistryKey($path) | ConvertTo-Json -Compress
      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
        if cmd.exit_status == 1001 && cmd.stderr =~ /InSpec: Failed to find registry key/
          # TODO: provide the stderr output
          @registry_cache = nil
        else
          @registry_cache = JSON.parse(cmd.stdout)
          # convert keys to lower case
          @registry_cache = Hash[@registry_cache.map do |key, value|
            [key.downcase, value]
          end]
        end
      rescue JSON::ParserError => _e
        @registry_cache = nil
      end
      @registry_cache
    end
registry_property_exists(regkey, property) click to toggle source
# File lib/inspec/resources/registry_key.rb, line 134
def registry_property_exists(regkey, property)
  return false if regkey.nil? || property.nil?

  # always ensure the key is lower case
  !regkey[prep_prop(property)].nil?
end
registry_property_type(regkey, property) click to toggle source
# File lib/inspec/resources/registry_key.rb, line 148
def registry_property_type(regkey, property)
  return nil unless registry_property_exists(regkey, property)

  # always ensure the key is lower case
  regkey[prep_prop(property)]["type"]
end
registry_property_value(regkey, property) click to toggle source
# File lib/inspec/resources/registry_key.rb, line 141
def registry_property_value(regkey, property)
  return nil unless registry_property_exists(regkey, property)

  # always ensure the key is lower case
  regkey[prep_prop(property)]["value"]
end