inspec 0.14.8 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -2
  3. data/bin/inspec +3 -4
  4. data/examples/inheritance/README.md +19 -0
  5. data/examples/inheritance/controls/example.rb +11 -0
  6. data/examples/inheritance/inspec.yml +10 -0
  7. data/lib/bundles/inspec-compliance/cli.rb +1 -4
  8. data/lib/bundles/inspec-supermarket/cli.rb +1 -4
  9. data/lib/inspec/dsl.rb +48 -55
  10. data/lib/inspec/profile.rb +6 -2
  11. data/lib/inspec/profile_context.rb +21 -8
  12. data/lib/inspec/runner.rb +17 -12
  13. data/lib/inspec/runner_rspec.rb +1 -0
  14. data/lib/inspec/version.rb +1 -1
  15. data/lib/resources/apache.rb +20 -18
  16. data/lib/resources/apache_conf.rb +92 -90
  17. data/lib/resources/apt.rb +92 -90
  18. data/lib/resources/audit_policy.rb +35 -33
  19. data/lib/resources/auditd_conf.rb +41 -39
  20. data/lib/resources/auditd_rules.rb +155 -153
  21. data/lib/resources/bond.rb +1 -1
  22. data/lib/resources/bridge.rb +97 -95
  23. data/lib/resources/command.rb +47 -45
  24. data/lib/resources/csv.rb +23 -21
  25. data/lib/resources/directory.rb +1 -1
  26. data/lib/resources/etc_group.rb +116 -114
  27. data/lib/resources/file.rb +1 -1
  28. data/lib/resources/gem.rb +39 -37
  29. data/lib/resources/group.rb +100 -98
  30. data/lib/resources/host.rb +103 -101
  31. data/lib/resources/inetd_conf.rb +42 -40
  32. data/lib/resources/ini.rb +15 -13
  33. data/lib/resources/interface.rb +106 -104
  34. data/lib/resources/iptables.rb +36 -34
  35. data/lib/resources/json.rb +64 -62
  36. data/lib/resources/kernel_module.rb +30 -28
  37. data/lib/resources/kernel_parameter.rb +44 -42
  38. data/lib/resources/limits_conf.rb +41 -39
  39. data/lib/resources/login_def.rb +38 -36
  40. data/lib/resources/mount.rb +43 -41
  41. data/lib/resources/mysql.rb +67 -65
  42. data/lib/resources/mysql_conf.rb +89 -87
  43. data/lib/resources/mysql_session.rb +46 -44
  44. data/lib/resources/npm.rb +35 -33
  45. data/lib/resources/ntp_conf.rb +44 -42
  46. data/lib/resources/oneget.rb +46 -44
  47. data/lib/resources/os.rb +22 -20
  48. data/lib/resources/os_env.rb +47 -45
  49. data/lib/resources/package.rb +213 -211
  50. data/lib/resources/parse_config.rb +59 -57
  51. data/lib/resources/passwd.rb +89 -87
  52. data/lib/resources/pip.rb +60 -58
  53. data/lib/resources/port.rb +352 -350
  54. data/lib/resources/postgres.rb +26 -24
  55. data/lib/resources/postgres_conf.rb +66 -64
  56. data/lib/resources/postgres_session.rb +47 -45
  57. data/lib/resources/processes.rb +56 -54
  58. data/lib/resources/registry_key.rb +150 -148
  59. data/lib/resources/script.rb +30 -28
  60. data/lib/resources/security_policy.rb +56 -54
  61. data/lib/resources/service.rb +638 -636
  62. data/lib/resources/shadow.rb +98 -96
  63. data/lib/resources/ssh_conf.rb +58 -56
  64. data/lib/resources/user.rb +363 -361
  65. data/lib/resources/windows_feature.rb +46 -44
  66. data/lib/resources/xinetd.rb +111 -109
  67. data/lib/resources/yaml.rb +16 -14
  68. data/lib/resources/yum.rb +107 -105
  69. data/lib/utils/base_cli.rb +18 -0
  70. data/test/helper.rb +2 -2
  71. data/test/unit/profile_context_test.rb +1 -1
  72. data/test/unit/resources/file_test.rb +1 -1
  73. data/test/unit/resources/mount_test.rb +1 -1
  74. metadata +5 -2
@@ -4,34 +4,36 @@
4
4
  # author: Christoph Hartmann
5
5
  # license: All rights reserved
6
6
 
7
- class Postgres < Inspec.resource(1)
8
- name 'postgres'
7
+ module Inspec::Resources
8
+ class Postgres < Inspec.resource(1)
9
+ name 'postgres'
9
10
 
10
- attr_reader :service, :data_dir, :conf_dir, :conf_path
11
- def initialize
12
- case inspec.os[:family]
13
- when 'ubuntu', 'debian'
14
- @service = 'postgresql'
15
- @data_dir = '/var/lib/postgresql'
16
- @version = inspec.command('ls /etc/postgresql/').stdout.chomp
17
- @conf_dir = "/etc/postgresql/#{@version}/main"
18
- @conf_path = File.join @conf_dir, 'postgresql.conf'
11
+ attr_reader :service, :data_dir, :conf_dir, :conf_path
12
+ def initialize
13
+ case inspec.os[:family]
14
+ when 'ubuntu', 'debian'
15
+ @service = 'postgresql'
16
+ @data_dir = '/var/lib/postgresql'
17
+ @version = inspec.command('ls /etc/postgresql/').stdout.chomp
18
+ @conf_dir = "/etc/postgresql/#{@version}/main"
19
+ @conf_path = File.join @conf_dir, 'postgresql.conf'
19
20
 
20
- when 'arch'
21
- @service = 'postgresql'
22
- @data_dir = '/var/lib/postgres/data'
23
- @conf_dir = '/var/lib/postgres/data'
24
- @conf_path = File.join @conf_dir, 'postgresql.conf'
21
+ when 'arch'
22
+ @service = 'postgresql'
23
+ @data_dir = '/var/lib/postgres/data'
24
+ @conf_dir = '/var/lib/postgres/data'
25
+ @conf_path = File.join @conf_dir, 'postgresql.conf'
25
26
 
26
- else
27
- @service = 'postgresql'
28
- @data_dir = '/var/lib/postgresql'
29
- @conf_dir = '/var/lib/pgsql/data'
30
- @conf_path = File.join @conf_dir, 'postgresql.conf'
27
+ else
28
+ @service = 'postgresql'
29
+ @data_dir = '/var/lib/postgresql'
30
+ @conf_dir = '/var/lib/pgsql/data'
31
+ @conf_path = File.join @conf_dir, 'postgresql.conf'
32
+ end
31
33
  end
32
- end
33
34
 
34
- def to_s
35
- 'PostgreSQL'
35
+ def to_s
36
+ 'PostgreSQL'
37
+ end
36
38
  end
37
39
  end
@@ -8,86 +8,88 @@ require 'utils/simpleconfig'
8
8
  require 'utils/find_files'
9
9
  require 'resources/postgres'
10
10
 
11
- class PostgresConf < Inspec.resource(1)
12
- name 'postgres_conf'
13
- desc 'Use the postgres_conf InSpec audit resource to test the contents of the configuration file for PostgreSQL, typically located at /etc/postgresql/<version>/main/postgresql.conf or /var/lib/postgres/data/postgresql.conf, depending on the platform.'
14
- example "
15
- describe postgres_conf do
16
- its('max_connections') { should eq '5' }
17
- end
18
- "
11
+ module Inspec::Resources
12
+ class PostgresConf < Inspec.resource(1)
13
+ name 'postgres_conf'
14
+ desc 'Use the postgres_conf InSpec audit resource to test the contents of the configuration file for PostgreSQL, typically located at /etc/postgresql/<version>/main/postgresql.conf or /var/lib/postgres/data/postgresql.conf, depending on the platform.'
15
+ example "
16
+ describe postgres_conf do
17
+ its('max_connections') { should eq '5' }
18
+ end
19
+ "
19
20
 
20
- include FindFiles
21
+ include FindFiles
21
22
 
22
- def initialize(conf_path = nil)
23
- @conf_path = conf_path || inspec.postgres.conf_path
24
- @conf_dir = File.expand_path(File.dirname(@conf_path))
25
- @files_contents = {}
26
- @content = nil
27
- @params = nil
28
- read_content
29
- end
23
+ def initialize(conf_path = nil)
24
+ @conf_path = conf_path || inspec.postgres.conf_path
25
+ @conf_dir = File.expand_path(File.dirname(@conf_path))
26
+ @files_contents = {}
27
+ @content = nil
28
+ @params = nil
29
+ read_content
30
+ end
30
31
 
31
- def content
32
- @content ||= read_content
33
- end
32
+ def content
33
+ @content ||= read_content
34
+ end
34
35
 
35
- def params(*opts)
36
- @params || read_content
37
- res = @params
38
- opts.each do |opt|
39
- res = res[opt] unless res.nil?
36
+ def params(*opts)
37
+ @params || read_content
38
+ res = @params
39
+ opts.each do |opt|
40
+ res = res[opt] unless res.nil?
41
+ end
42
+ res
40
43
  end
41
- res
42
- end
43
44
 
44
- def read_content
45
- @content = ''
46
- @params = {}
45
+ def read_content
46
+ @content = ''
47
+ @params = {}
47
48
 
48
- # skip if the main configuration file doesn't exist
49
- if !inspec.file(@conf_path).file?
50
- return skip_resource "Can't find file \"#{@conf_path}\""
51
- end
52
- raw_conf = read_file(@conf_path)
53
- if raw_conf.empty? && inspec.file(@conf_path).size > 0
54
- return skip_resource("Can't read file \"#{@conf_path}\"")
55
- end
49
+ # skip if the main configuration file doesn't exist
50
+ if !inspec.file(@conf_path).file?
51
+ return skip_resource "Can't find file \"#{@conf_path}\""
52
+ end
53
+ raw_conf = read_file(@conf_path)
54
+ if raw_conf.empty? && inspec.file(@conf_path).size > 0
55
+ return skip_resource("Can't read file \"#{@conf_path}\"")
56
+ end
56
57
 
57
- to_read = [@conf_path]
58
- until to_read.empty?
59
- raw_conf = read_file(to_read[0])
60
- @content += raw_conf
58
+ to_read = [@conf_path]
59
+ until to_read.empty?
60
+ raw_conf = read_file(to_read[0])
61
+ @content += raw_conf
61
62
 
62
- params = SimpleConfig.new(raw_conf).params
63
- @params.merge!(params)
63
+ params = SimpleConfig.new(raw_conf).params
64
+ @params.merge!(params)
64
65
 
65
- to_read = to_read.drop(1)
66
- # see if there is more config files to include
66
+ to_read = to_read.drop(1)
67
+ # see if there is more config files to include
67
68
 
68
- to_read += include_files(params).find_all do |fp|
69
- not @files_contents.key? fp
69
+ to_read += include_files(params).find_all do |fp|
70
+ not @files_contents.key? fp
71
+ end
70
72
  end
73
+ @content
71
74
  end
72
- @content
73
- end
74
75
 
75
- def include_files(params)
76
- include_files = params['include'] || []
77
- include_files += params['include_if_exists'] || []
78
- dirs = params['include_dir'] || []
79
- dirs.each do |dir|
80
- dir = File.join(@conf_dir, dir) if dir[0] != '/'
81
- include_files += find_files(dir, depth: 1, type: 'file')
76
+ def include_files(params)
77
+ include_files = params['include'] || []
78
+ include_files += params['include_if_exists'] || []
79
+ dirs = params['include_dir'] || []
80
+ dirs.each do |dir|
81
+ dir = File.join(@conf_dir, dir) if dir[0] != '/'
82
+ include_files += find_files(dir, depth: 1, type: 'file')
83
+ end
84
+ include_files
82
85
  end
83
- include_files
84
- end
85
86
 
86
- def read_file(path)
87
- @files_contents[path] ||= inspec.file(path).content
88
- end
87
+ def read_file(path)
88
+ @files_contents[path] ||= inspec.file(path).content
89
+ end
89
90
 
90
- def to_s
91
- 'PostgreSQL Configuration'
91
+ def to_s
92
+ 'PostgreSQL Configuration'
93
+ end
92
94
  end
93
95
  end
@@ -4,59 +4,61 @@
4
4
  # author: Christoph Hartmann
5
5
  # license: All rights reserved
6
6
 
7
- class Lines
8
- attr_reader :output
7
+ module Inspec::Resources
8
+ class Lines
9
+ attr_reader :output
9
10
 
10
- def initialize(raw, desc)
11
- @output = raw
12
- @desc = desc
13
- end
11
+ def initialize(raw, desc)
12
+ @output = raw
13
+ @desc = desc
14
+ end
14
15
 
15
- def lines
16
- output.split("\n")
17
- end
16
+ def lines
17
+ output.split("\n")
18
+ end
18
19
 
19
- def to_s
20
- @desc
20
+ def to_s
21
+ @desc
22
+ end
21
23
  end
22
- end
23
24
 
24
- class PostgresSession < Inspec.resource(1)
25
- name 'postgres_session'
26
- desc 'Use the postgres_session InSpec audit resource to test SQL commands run against a PostgreSQL database.'
27
- example "
28
- sql = postgres_session('username', 'password')
25
+ class PostgresSession < Inspec.resource(1)
26
+ name 'postgres_session'
27
+ desc 'Use the postgres_session InSpec audit resource to test SQL commands run against a PostgreSQL database.'
28
+ example "
29
+ sql = postgres_session('username', 'password')
29
30
 
30
- describe sql.query('SELECT * FROM pg_shadow WHERE passwd IS NULL;') do
31
- its('output') { should eq('') }
32
- end
33
- "
31
+ describe sql.query('SELECT * FROM pg_shadow WHERE passwd IS NULL;') do
32
+ its('output') { should eq('') }
33
+ end
34
+ "
34
35
 
35
- def initialize(user, pass)
36
- @user = user || 'postgres'
37
- @pass = pass
38
- end
36
+ def initialize(user, pass)
37
+ @user = user || 'postgres'
38
+ @pass = pass
39
+ end
39
40
 
40
- def query(query, db = [])
41
- dbs = db.map { |x| "-d #{x}" }.join(' ')
42
- # TODO: simple escape, must be handled by a library
43
- # that does this securely
44
- escaped_query = query.gsub(/\\/, '\\\\').gsub(/"/, '\\"').gsub(/\$/, '\\$')
45
- # run the query
46
- cmd = inspec.command("PGPASSWORD='#{@pass}' psql -U #{@user} #{dbs} -h localhost -c \"#{escaped_query}\"")
47
- out = cmd.stdout + "\n" + cmd.stderr
48
- if cmd.exit_status != 0 or
49
- out =~ /could not connect to .*/ or
50
- out.downcase =~ /^error/
51
- # skip this test if the server can't run the query
52
- skip_resource "Can't read run query #{query.inspect} on postgres_session: #{out}"
53
- else
54
- # remove the whole header (i.e. up to the first ^-----+------+------$)
55
- # remove the tail
56
- lines = cmd.stdout
57
- .sub(/(.*\n)+([-]+[+])*[-]+\n/, '')
58
- .sub(/\n[^\n]*\n\n$/, '')
59
- Lines.new(lines.strip, "PostgreSQL query: #{query}")
41
+ def query(query, db = [])
42
+ dbs = db.map { |x| "-d #{x}" }.join(' ')
43
+ # TODO: simple escape, must be handled by a library
44
+ # that does this securely
45
+ escaped_query = query.gsub(/\\/, '\\\\').gsub(/"/, '\\"').gsub(/\$/, '\\$')
46
+ # run the query
47
+ cmd = inspec.command("PGPASSWORD='#{@pass}' psql -U #{@user} #{dbs} -h localhost -c \"#{escaped_query}\"")
48
+ out = cmd.stdout + "\n" + cmd.stderr
49
+ if cmd.exit_status != 0 or
50
+ out =~ /could not connect to .*/ or
51
+ out.downcase =~ /^error/
52
+ # skip this test if the server can't run the query
53
+ skip_resource "Can't read run query #{query.inspect} on postgres_session: #{out}"
54
+ else
55
+ # remove the whole header (i.e. up to the first ^-----+------+------$)
56
+ # remove the tail
57
+ lines = cmd.stdout
58
+ .sub(/(.*\n)+([-]+[+])*[-]+\n/, '')
59
+ .sub(/\n[^\n]*\n\n$/, '')
60
+ Lines.new(lines.strip, "PostgreSQL query: #{query}")
61
+ end
60
62
  end
61
63
  end
62
64
  end
@@ -4,70 +4,72 @@
4
4
  # author: Christoph Hartmann
5
5
  # license: All rights reserved
6
6
 
7
- class Processes < Inspec.resource(1)
8
- name 'processes'
9
- desc 'Use the processes InSpec audit resource to test properties for programs that are running on the system.'
10
- example "
11
- describe processes('mysqld') do
12
- its('list.length') { should eq 1 }
13
- its('users') { should eq ['mysql'] }
14
- its('states') { should include 'S' }
15
- end
16
- "
7
+ module Inspec::Resources
8
+ class Processes < Inspec.resource(1)
9
+ name 'processes'
10
+ desc 'Use the processes InSpec audit resource to test properties for programs that are running on the system.'
11
+ example "
12
+ describe processes('mysqld') do
13
+ its('list.length') { should eq 1 }
14
+ its('users') { should eq ['mysql'] }
15
+ its('states') { should include 'S' }
16
+ end
17
+ "
17
18
 
18
- attr_reader :list,
19
- :users,
20
- :states
19
+ attr_reader :list,
20
+ :users,
21
+ :states
21
22
 
22
- def initialize(grep)
23
- # turn into a regexp if it isn't one yet
24
- if grep.class == String
25
- grep = '(/[^/]*)*'+grep if grep[0] != '/'
26
- grep = Regexp.new('^' + grep + '(\s|$)')
27
- end
23
+ def initialize(grep)
24
+ # turn into a regexp if it isn't one yet
25
+ if grep.class == String
26
+ grep = '(/[^/]*)*'+grep if grep[0] != '/'
27
+ grep = Regexp.new('^' + grep + '(\s|$)')
28
+ end
28
29
 
29
- all_cmds = ps_aux
30
- @list = all_cmds.find_all do |hm|
31
- hm[:command] =~ grep
32
- end
30
+ all_cmds = ps_aux
31
+ @list = all_cmds.find_all do |hm|
32
+ hm[:command] =~ grep
33
+ end
33
34
 
34
- { users: :user,
35
- states: :stat }.each do |var, key|
36
- instance_variable_set("@#{var}", @list.map { |l| l[key] }.uniq)
35
+ { users: :user,
36
+ states: :stat }.each do |var, key|
37
+ instance_variable_set("@#{var}", @list.map { |l| l[key] }.uniq)
38
+ end
37
39
  end
38
- end
39
40
 
40
- def to_s
41
- 'Processes'
42
- end
41
+ def to_s
42
+ 'Processes'
43
+ end
43
44
 
44
- private
45
+ private
45
46
 
46
- def ps_aux
47
- # get all running processes
48
- cmd = inspec.command('ps aux')
49
- all = cmd.stdout.split("\n")[1..-1]
50
- return [] if all.nil?
47
+ def ps_aux
48
+ # get all running processes
49
+ cmd = inspec.command('ps aux')
50
+ all = cmd.stdout.split("\n")[1..-1]
51
+ return [] if all.nil?
51
52
 
52
- lines = all.map do |line|
53
- # user 32296 0.0 0.0 42592 7972 pts/15 Ss+ Apr06 0:00 zsh
54
- line.match(/^([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+(.*)$/)
55
- end.compact
53
+ lines = all.map do |line|
54
+ # user 32296 0.0 0.0 42592 7972 pts/15 Ss+ Apr06 0:00 zsh
55
+ line.match(/^([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+(.*)$/)
56
+ end.compact
56
57
 
57
- lines.map do |m|
58
- {
59
- user: m[1],
60
- pid: m[2],
61
- cpu: m[3],
62
- mem: m[4],
63
- vsz: m[5],
64
- rss: m[6],
65
- tty: m[7],
66
- stat: m[8],
67
- start: m[9],
68
- time: m[10],
69
- command: m[11],
70
- }
58
+ lines.map do |m|
59
+ {
60
+ user: m[1],
61
+ pid: m[2],
62
+ cpu: m[3],
63
+ mem: m[4],
64
+ vsz: m[5],
65
+ rss: m[6],
66
+ tty: m[7],
67
+ stat: m[8],
68
+ start: m[9],
69
+ time: m[10],
70
+ command: m[11],
71
+ }
72
+ end
71
73
  end
72
74
  end
73
75
  end
@@ -10,174 +10,176 @@ require 'json'
10
10
  # its('Start') { should eq 2 }
11
11
  # end
12
12
 
13
- class RegistryKey < Inspec.resource(1)
14
- name 'registry_key'
15
- desc 'Use the registry_key InSpec audit resource to test key values in the Microsoft Windows registry.'
16
- example "
17
- describe registry_key('path\to\key') do
18
- its('name') { should eq 'value' }
13
+ module Inspec::Resources
14
+ class RegistryKey < Inspec.resource(1)
15
+ name 'registry_key'
16
+ desc 'Use the registry_key InSpec audit resource to test key values in the Microsoft Windows registry.'
17
+ example "
18
+ describe registry_key('path\to\key') do
19
+ its('name') { should eq 'value' }
20
+ end
21
+ "
22
+
23
+ attr_accessor :reg_key
24
+
25
+ def initialize(name, reg_key = nil)
26
+ # if we have one parameter, we use it as name
27
+ reg_key ||= name
28
+ @name = name
29
+ @reg_key = reg_key
30
+
31
+ return skip_resource 'The `registry_key` resource is not supported on your OS yet.' if !inspec.os.windows?
19
32
  end
20
- "
21
33
 
22
- attr_accessor :reg_key
23
-
24
- def initialize(name, reg_key = nil)
25
- # if we have one parameter, we use it as name
26
- reg_key ||= name
27
- @name = name
28
- @reg_key = reg_key
29
-
30
- return skip_resource 'The `registry_key` resource is not supported on your OS yet.' if !inspec.os.windows?
31
- end
32
-
33
- def exists?
34
- !registry_key(@reg_key).nil?
35
- end
36
-
37
- def has_value?(value)
38
- val = registry_key(@reg_key)
39
- !val.nil? && registry_property_value(val, '(default)') == value ? true : false
40
- end
34
+ def exists?
35
+ !registry_key(@reg_key).nil?
36
+ end
41
37
 
42
- def has_property?(property_name, property_type = nil)
43
- val = registry_key(@reg_key)
44
- !val.nil? && registry_property_exists(val, property_name) && (property_type.nil? || registry_property_type(val, property_name) == map2type(property_type)) ? true : false
45
- end
38
+ def has_value?(value)
39
+ val = registry_key(@reg_key)
40
+ !val.nil? && registry_property_value(val, '(default)') == value ? true : false
41
+ end
46
42
 
47
- # deactivate rubocop, because we need to stay compatible with Serverspe
48
- # rubocop:disable Style/OptionalArguments
49
- def has_property_value?(property_name, property_type = nil, value)
50
- # rubocop:enable Style/OptionalArguments
51
- val = registry_key(@reg_key)
43
+ def has_property?(property_name, property_type = nil)
44
+ val = registry_key(@reg_key)
45
+ !val.nil? && registry_property_exists(val, property_name) && (property_type.nil? || registry_property_type(val, property_name) == map2type(property_type)) ? true : false
46
+ end
52
47
 
53
- # convert value to binary if required
54
- value = value.bytes if !property_type.nil? && map2type(property_type) == 3 && !value.is_a?(Array)
48
+ # deactivate rubocop, because we need to stay compatible with Serverspe
49
+ # rubocop:disable Style/OptionalArguments
50
+ def has_property_value?(property_name, property_type = nil, value)
51
+ # rubocop:enable Style/OptionalArguments
52
+ val = registry_key(@reg_key)
55
53
 
56
- !val.nil? && registry_property_value(val, property_name) == value && (property_type.nil? || registry_property_type(val, property_name) == map2type(property_type)) ? true : false
57
- end
54
+ # convert value to binary if required
55
+ value = value.bytes if !property_type.nil? && map2type(property_type) == 3 && !value.is_a?(Array)
58
56
 
59
- # returns nil, if not existant or value
60
- def method_missing(meth)
61
- # get data
62
- val = registry_key(@reg_key)
63
- registry_property_value(val, meth)
64
- end
57
+ !val.nil? && registry_property_value(val, property_name) == value && (property_type.nil? || registry_property_type(val, property_name) == map2type(property_type)) ? true : false
58
+ end
65
59
 
66
- def to_s
67
- "Registry Key #{@name}"
68
- end
60
+ # returns nil, if not existant or value
61
+ def method_missing(meth)
62
+ # get data
63
+ val = registry_key(@reg_key)
64
+ registry_property_value(val, meth)
65
+ end
69
66
 
70
- private
67
+ def to_s
68
+ "Registry Key #{@name}"
69
+ end
71
70
 
72
- def prep_prop(property)
73
- property.to_s.downcase
74
- end
71
+ private
75
72
 
76
- def registry_property_exists(regkey, property)
77
- return false if regkey.nil? || property.nil?
78
- # always ensure the key is lower case
79
- !regkey[prep_prop(property)].nil?
80
- end
73
+ def prep_prop(property)
74
+ property.to_s.downcase
75
+ end
81
76
 
82
- def registry_property_value(regkey, property)
83
- return nil if !registry_property_exists(regkey, property)
84
- # always ensure the key is lower case
85
- regkey[prep_prop(property)]['value']
86
- end
77
+ def registry_property_exists(regkey, property)
78
+ return false if regkey.nil? || property.nil?
79
+ # always ensure the key is lower case
80
+ !regkey[prep_prop(property)].nil?
81
+ end
87
82
 
88
- def registry_property_type(regkey, property)
89
- return nil if !registry_property_exists(regkey, property)
90
- # always ensure the key is lower case
91
- regkey[prep_prop(property)]['type']
92
- end
83
+ def registry_property_value(regkey, property)
84
+ return nil if !registry_property_exists(regkey, property)
85
+ # always ensure the key is lower case
86
+ regkey[prep_prop(property)]['value']
87
+ end
93
88
 
94
- def registry_key(path)
95
- return @registry_cache if defined?(@registry_cache)
96
-
97
- # load registry key and all properties
98
- script = <<-EOH
99
- $reg = Get-Item 'Registry::#{path}'
100
- $object = New-Object -Type PSObject
101
- $reg.Property | ForEach-Object {
102
- $key = $_
103
- if ("(default)".Equals($key)) { $key = '' }
104
- $value = New-Object psobject -Property @{
105
- "value" = $reg.GetValue($key);
106
- "type" = $reg.GetValueKind($key);
107
- }
108
- $object | Add-Member –MemberType NoteProperty –Name $_ –Value $value
109
- }
110
- $object | ConvertTo-Json
111
- EOH
112
-
113
- cmd = inspec.script(script)
114
-
115
- # cannot rely on exit code for now, successful command returns exit code 1
116
- # return nil if cmd.exit_status != 0, try to parse json
117
- begin
118
- @registry_cache = JSON.parse(cmd.stdout)
119
- # convert keys to lower case
120
- @registry_cache = Hash[@registry_cache.map do |key, value|
121
- [key.downcase, value]
122
- end]
123
- rescue JSON::ParserError => _e
124
- @registry_cache = nil
89
+ def registry_property_type(regkey, property)
90
+ return nil if !registry_property_exists(regkey, property)
91
+ # always ensure the key is lower case
92
+ regkey[prep_prop(property)]['type']
125
93
  end
126
94
 
127
- @registry_cache
128
- end
95
+ def registry_key(path)
96
+ return @registry_cache if defined?(@registry_cache)
97
+
98
+ # load registry key and all properties
99
+ script = <<-EOH
100
+ $reg = Get-Item 'Registry::#{path}'
101
+ $object = New-Object -Type PSObject
102
+ $reg.Property | ForEach-Object {
103
+ $key = $_
104
+ if ("(default)".Equals($key)) { $key = '' }
105
+ $value = New-Object psobject -Property @{
106
+ "value" = $reg.GetValue($key);
107
+ "type" = $reg.GetValueKind($key);
108
+ }
109
+ $object | Add-Member –MemberType NoteProperty –Name $_ –Value $value
110
+ }
111
+ $object | ConvertTo-Json
112
+ EOH
113
+
114
+ cmd = inspec.script(script)
115
+
116
+ # cannot rely on exit code for now, successful command returns exit code 1
117
+ # return nil if cmd.exit_status != 0, try to parse json
118
+ begin
119
+ @registry_cache = JSON.parse(cmd.stdout)
120
+ # convert keys to lower case
121
+ @registry_cache = Hash[@registry_cache.map do |key, value|
122
+ [key.downcase, value]
123
+ end]
124
+ rescue JSON::ParserError => _e
125
+ @registry_cache = nil
126
+ end
127
+
128
+ @registry_cache
129
+ end
129
130
 
130
- # Registry key value types
131
- # @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms724884(v=vs.85).aspx
132
- # REG_NONE 0
133
- # REG_SZ 1
134
- # REG_EXPAND_SZ 2
135
- # REG_BINARY 3
136
- # REG_DWORD 4
137
- # REG_DWORD_LITTLE_ENDIAN 4
138
- # REG_DWORD_BIG_ENDIAN 5
139
- # REG_LINK 6
140
- # REG_MULTI_SZ 7
141
- # REG_RESOURCE_LIST 8
142
- # REG_FULL_RESOURCE_DESCRIPTOR 9
143
- # REG_RESOURCE_REQUIREMENTS_LIST 10
144
- # REG_QWORD 11
145
- # REG_QWORD_LITTLE_ENDIAN 11
146
- def map2type(symbol)
147
- options = {}
148
-
149
- # chef symbols, we prefer those
150
- options[:binary] = 3
151
- options[:string] = 1
152
- options[:multi_string] = 7
153
- options[:expand_string] = 2
154
- options[:dword] = 4
155
- options[:dword_big_endian] = 5
156
- options[:qword] = 11
157
-
158
- # serverspec symbols
159
- options[:type_string] = 1
160
- options[:type_binary] = 3
161
- options[:type_dword] = 4
162
- options[:type_qword] = 11
163
- options[:type_multistring] = 7
164
- options[:type_expandstring] = 2
165
-
166
- options[symbol]
131
+ # Registry key value types
132
+ # @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms724884(v=vs.85).aspx
133
+ # REG_NONE 0
134
+ # REG_SZ 1
135
+ # REG_EXPAND_SZ 2
136
+ # REG_BINARY 3
137
+ # REG_DWORD 4
138
+ # REG_DWORD_LITTLE_ENDIAN 4
139
+ # REG_DWORD_BIG_ENDIAN 5
140
+ # REG_LINK 6
141
+ # REG_MULTI_SZ 7
142
+ # REG_RESOURCE_LIST 8
143
+ # REG_FULL_RESOURCE_DESCRIPTOR 9
144
+ # REG_RESOURCE_REQUIREMENTS_LIST 10
145
+ # REG_QWORD 11
146
+ # REG_QWORD_LITTLE_ENDIAN 11
147
+ def map2type(symbol)
148
+ options = {}
149
+
150
+ # chef symbols, we prefer those
151
+ options[:binary] = 3
152
+ options[:string] = 1
153
+ options[:multi_string] = 7
154
+ options[:expand_string] = 2
155
+ options[:dword] = 4
156
+ options[:dword_big_endian] = 5
157
+ options[:qword] = 11
158
+
159
+ # serverspec symbols
160
+ options[:type_string] = 1
161
+ options[:type_binary] = 3
162
+ options[:type_dword] = 4
163
+ options[:type_qword] = 11
164
+ options[:type_multistring] = 7
165
+ options[:type_expandstring] = 2
166
+
167
+ options[symbol]
168
+ end
167
169
  end
168
- end
169
170
 
170
- # for compatability with serverspec
171
- # this is deprecated syntax and will be removed in future versions
172
- class WindowsRegistryKey < RegistryKey
173
- name 'windows_registry_key'
171
+ # for compatability with serverspec
172
+ # this is deprecated syntax and will be removed in future versions
173
+ class WindowsRegistryKey < RegistryKey
174
+ name 'windows_registry_key'
174
175
 
175
- def initialize(name)
176
- deprecated
177
- super(name)
178
- end
176
+ def initialize(name)
177
+ deprecated
178
+ super(name)
179
+ end
179
180
 
180
- def deprecated
181
- warn '[DEPRECATION] `windows_registry_key(reg_key)` is deprecated. Please use `registry_key(\'path\to\key\')` instead.'
181
+ def deprecated
182
+ warn '[DEPRECATION] `windows_registry_key(reg_key)` is deprecated. Please use `registry_key(\'path\to\key\')` instead.'
183
+ end
182
184
  end
183
185
  end