inspec-core 4.33.1 → 4.36.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ec42612f75dc95f62517b85b024c039ad15965f7c98dfaecb9494161b9f85611
4
- data.tar.gz: 6373b89393e737cacdcb859ca510758afb9ce7e16d89e90d86877205a3d8d335
3
+ metadata.gz: 2c3d7a6b401a4a92a2dbe1342499857065d9643baeed19d2b1e5af77672be3d8
4
+ data.tar.gz: 907c48ac504a9a8588e41a65edfbafc3726c17ce59c5a5a8b3e5c83000fa08db
5
5
  SHA512:
6
- metadata.gz: f1591b7c166d00fe78037f703eb55292384b2c2b13195db150da008b198424177809078db9509054af664f91aca8bae06f93f41939d808263cc78baf0414f29c
7
- data.tar.gz: 5124bfc3a8b676bd097efc319233fec94d3fd3739b727e1b92678c7929d280c093c46136b80607f166d164e0bd85586b9ce560e2ebed0eadbd7f35d09bd517b9
6
+ metadata.gz: 5685428db9251aae0e26db8cc0ab81f247115aa70152472421e560cf97c17486e8f656a9be158ba3fbaa00bb078a1fb12eb5077a6d16a4883b052a9aba5c0869
7
+ data.tar.gz: baf44fe69d48134e7d6a8760ceb245c10a29a6e423d8afda68ac35225bba6f7a7a0e21f815d5f4b7fb4206b6f4080b01b9e5be16f1e2f030b2f594c53c215b22
data/inspec-core.gemspec CHANGED
@@ -35,7 +35,7 @@ Gem::Specification.new do |spec|
35
35
  spec.add_dependency "mixlib-log", "~> 3.0"
36
36
  spec.add_dependency "sslshake", "~> 1.2"
37
37
  spec.add_dependency "parallel", "~> 1.9"
38
- spec.add_dependency "faraday", ">= 0.9.0", "< 1.4"
38
+ spec.add_dependency "faraday", ">= 0.9.0", "< 1.5"
39
39
  spec.add_dependency "faraday_middleware", "~> 1.0"
40
40
  spec.add_dependency "tty-table", "~> 0.10"
41
41
  spec.add_dependency "tty-prompt", "~> 0.17"
@@ -194,6 +194,7 @@ module Inspec
194
194
 
195
195
  # Check if the given control exist in the --controls option
196
196
  def control_exist_in_controls_list?(id)
197
+ id_exist_in_list = false
197
198
  if profile_config_exist?
198
199
  id_exist_in_list = @conf["profile"].include_controls_list.any? do |inclusion|
199
200
  # Try to see if the inclusion is a regex, and if it matches
data/lib/inspec/input.rb CHANGED
@@ -19,12 +19,17 @@ module Inspec
19
19
  attr_accessor :input_name
20
20
  attr_accessor :input_value
21
21
  attr_accessor :input_type
22
+ attr_accessor :input_pattern
22
23
  end
23
24
 
24
25
  class TypeError < Error
25
26
  attr_accessor :input_type
26
27
  end
27
28
 
29
+ class PatternError < Error
30
+ attr_accessor :input_pattern
31
+ end
32
+
28
33
  class RequiredError < Error
29
34
  attr_accessor :input_name
30
35
  end
@@ -56,7 +61,6 @@ module Inspec
56
61
 
57
62
  def initialize(properties = {})
58
63
  @value_has_been_set = false
59
-
60
64
  properties.each do |prop_name, prop_value|
61
65
  if EVENT_PROPERTIES.include? prop_name
62
66
  # OK, save the property
@@ -174,7 +178,7 @@ module Inspec
174
178
  # are free to go higher.
175
179
  DEFAULT_PRIORITY_FOR_VALUE_SET = 60
176
180
 
177
- attr_reader :description, :events, :identifier, :name, :required, :sensitive, :title, :type
181
+ attr_reader :description, :events, :identifier, :name, :required, :sensitive, :title, :type, :pattern
178
182
 
179
183
  def initialize(name, options = {})
180
184
  @name = name
@@ -192,7 +196,6 @@ module Inspec
192
196
  # debugging record of when and how the value changed.
193
197
  @events = []
194
198
  events.push make_creation_event(options)
195
-
196
199
  update(options)
197
200
  end
198
201
 
@@ -213,6 +216,7 @@ module Inspec
213
216
  def update(options)
214
217
  _update_set_metadata(options)
215
218
  normalize_type_restriction!
219
+ normalize_pattern_restriction!
216
220
 
217
221
  # Values are set by passing events in; but we can also infer an event.
218
222
  if options.key?(:value) || options.key?(:default)
@@ -227,6 +231,7 @@ module Inspec
227
231
  events << options[:event] if options.key? :event
228
232
 
229
233
  enforce_type_restriction!
234
+ enforce_pattern_restriction!
230
235
  end
231
236
 
232
237
  # We can determine a value:
@@ -268,6 +273,7 @@ module Inspec
268
273
  @identifier = options[:identifier] if options.key?(:identifier) # TODO: determine if this is ever used
269
274
  @type = options[:type] if options.key?(:type)
270
275
  @sensitive = options[:sensitive] if options.key?(:sensitive)
276
+ @pattern = options[:pattern] if options.key?(:pattern)
271
277
  end
272
278
 
273
279
  def make_creation_event(options)
@@ -310,7 +316,9 @@ module Inspec
310
316
  file: location.path,
311
317
  line: location.lineno
312
318
  )
319
+
313
320
  enforce_type_restriction!
321
+ enforce_pattern_restriction!
314
322
  end
315
323
 
316
324
  def value
@@ -324,7 +332,7 @@ module Inspec
324
332
 
325
333
  def to_hash
326
334
  as_hash = { name: name, options: {} }
327
- %i{description title identifier type required value sensitive}.each do |field|
335
+ %i{description title identifier type required value sensitive pattern}.each do |field|
328
336
  val = send(field)
329
337
  next if val.nil?
330
338
 
@@ -407,6 +415,33 @@ module Inspec
407
415
  @type = type_req
408
416
  end
409
417
 
418
+ def enforce_pattern_restriction!
419
+ return unless pattern
420
+ return unless has_value?
421
+
422
+ string_value = current_value(false).to_s
423
+
424
+ valid_pattern = string_value.match?(pattern)
425
+ unless valid_pattern
426
+ error = Inspec::Input::ValidationError.new
427
+ error.input_name = @name
428
+ error.input_value = string_value
429
+ error.input_pattern = pattern
430
+ raise error, "Input '#{error.input_name}' with value '#{error.input_value}' does not validate to pattern '#{error.input_pattern}'."
431
+ end
432
+ end
433
+
434
+ def normalize_pattern_restriction!
435
+ return unless pattern
436
+
437
+ unless valid_regexp?(pattern)
438
+ error = Inspec::Input::PatternError.new
439
+ error.input_pattern = pattern
440
+ raise error, "Pattern '#{error.input_pattern}' is not a valid regex pattern."
441
+ end
442
+ @pattern = pattern
443
+ end
444
+
410
445
  def valid_numeric?(value)
411
446
  Float(value)
412
447
  true
@@ -325,6 +325,7 @@ module Inspec
325
325
  type: input_options[:type],
326
326
  required: input_options[:required],
327
327
  sensitive: input_options[:sensitive],
328
+ pattern: input_options[:pattern],
328
329
  event: evt
329
330
  )
330
331
  end
@@ -20,7 +20,7 @@ module Inspec
20
20
 
21
21
  def to_hash
22
22
  as_hash = { name: name, options: {} }
23
- %i{description title identifier type required value}.each do |field|
23
+ %i{description title identifier type required value pattern}.each do |field|
24
24
  val = send(field)
25
25
  next if val.nil?
26
26
 
@@ -103,6 +103,7 @@ require "inspec/resources/rabbitmq_config"
103
103
  require "inspec/resources/registry_key"
104
104
  require "inspec/resources/security_identifier"
105
105
  require "inspec/resources/security_policy"
106
+ require "inspec/resources/selinux"
106
107
  require "inspec/resources/service"
107
108
  require "inspec/resources/shadow"
108
109
  require "inspec/resources/ssh_config"
@@ -49,10 +49,11 @@ module Inspec::Resources
49
49
 
50
50
  filter = FilterTable.create
51
51
  filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
52
- filter.register_column(:names, field: "name")
53
- .register_column(:gids, field: "gid")
54
- .register_column(:domains, field: "domain")
55
- .register_column(:members, field: "members", style: :simple)
52
+ filter.register_column(:names, field: "name")
53
+ .register_column(:gids, field: "gid")
54
+ .register_column(:domains, field: "domain")
55
+ .register_column(:members, field: "members", style: :simple)
56
+ .register_column(:members_array, field: "members_array", style: :simple)
56
57
  filter.install_filter_methods_on_resource(self, :collect_group_details)
57
58
 
58
59
  def to_s
@@ -63,7 +64,13 @@ module Inspec::Resources
63
64
 
64
65
  # collects information about every group
65
66
  def collect_group_details
66
- return @groups_cache ||= @group_provider.groups unless @group_provider.nil?
67
+ unless @group_provider.nil?
68
+ modified_groups_info = @group_provider.groups
69
+ unless modified_groups_info.empty?
70
+ modified_groups_info.each { |hashmap| hashmap["members_array"] = hashmap["members"].is_a?(Array) ? hashmap["members"] : hashmap["members"]&.split(",") }
71
+ end
72
+ return @groups_cache ||= modified_groups_info
73
+ end
67
74
 
68
75
  []
69
76
  end
@@ -111,7 +118,11 @@ module Inspec::Resources
111
118
  end
112
119
 
113
120
  def members
114
- flatten_entry(group_info, "members")
121
+ flatten_entry(group_info, "members") || empty_value_for_members
122
+ end
123
+
124
+ def members_array
125
+ flatten_entry(group_info, "members_array") || []
115
126
  end
116
127
 
117
128
  def local
@@ -141,6 +152,10 @@ module Inspec::Resources
141
152
  group = @group.dup
142
153
  @groups_cache ||= inspec.groups.where { name == group }
143
154
  end
155
+
156
+ def empty_value_for_members
157
+ inspec.os.windows? ? [] : ""
158
+ end
144
159
  end
145
160
 
146
161
  class GroupInfo
@@ -0,0 +1,154 @@
1
+ require "inspec/resources/command"
2
+ require "inspec/utils/filter"
3
+
4
+ module Inspec::Resources
5
+ class SelinuxModuleFilter
6
+ # use filtertable for SELinux Modules
7
+ filter = FilterTable.create
8
+ filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
9
+ filter.register_column(:names, field: :name)
10
+ filter.register_column(:status, field: :status)
11
+ filter.register_column(:states, field: :state)
12
+ filter.register_column(:priorities , field: :priority)
13
+ filter.register_custom_matcher(:enabled?) { |x| x.states[0] == "enabled" }
14
+ filter.register_custom_matcher(:installed?) { |x| x.status[0] == "installed" }
15
+ filter.install_filter_methods_on_resource(self, :modules)
16
+
17
+ attr_reader :modules
18
+ def initialize(modules)
19
+ @modules = modules
20
+ end
21
+
22
+ def to_s
23
+ "SELinux modules"
24
+ end
25
+ end
26
+
27
+ class SelinuxBooleanFilter
28
+ # use filtertable for SELinux Booleans
29
+ filter = FilterTable.create
30
+ filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
31
+ filter.register_column(:names, field: :name)
32
+ filter.register_column(:states, field: :state)
33
+ filter.register_column(:defaults, field: :default)
34
+ filter.register_custom_matcher(:on?) { |x| x.states[0] == "on" }
35
+ filter.install_filter_methods_on_resource(self, :booleans)
36
+
37
+ attr_reader :booleans
38
+ def initialize(booleans)
39
+ @booleans = booleans
40
+ end
41
+
42
+ def to_s
43
+ "SELinux booleans"
44
+ end
45
+ end
46
+
47
+ class Selinux < Inspec.resource(1)
48
+ name "selinux"
49
+ supports platform: "linux"
50
+
51
+ desc "Use the selinux Chef InSpec resource to test the configuration data of the SELinux policy, SELinux modules, and SELinux booleans."
52
+
53
+ example <<~EXAMPLE
54
+ describe selinux do
55
+ it { should be_installed }
56
+ it { should be_disabled }
57
+ it { should be_permissive }
58
+ it { should be_enforcing }
59
+ end
60
+
61
+ describe selinux do
62
+ its('policy') { should eq "targeted"}
63
+ end
64
+
65
+ describe selinux.modules.where("zebra") do
66
+ it { should exist }
67
+ it { should be_installed }
68
+ it { should be_enabled }
69
+ end
70
+
71
+ describe selinux.modules.where(status: "installed") do
72
+ it { should exist }
73
+ its('count') { should cmp 404 }
74
+ end
75
+
76
+ describe selinux.booleans.where(name: "xend_run_blktap") do
77
+ it { should be_on }
78
+ end
79
+
80
+ describe selinux.booleans.where { name == "xend_run_blktap" && state == "on" } do
81
+ it { should exist }
82
+ end
83
+ EXAMPLE
84
+
85
+ def initialize(selinux_path = "/etc/selinux/config")
86
+ @path = selinux_path
87
+ cmd = inspec.command("sestatus")
88
+
89
+ if cmd.exit_status != 0
90
+ # `sestatus` command not found error message comes in stdout so handling both here
91
+ out = cmd.stdout + "\n" + cmd.stderr
92
+ return skip_resource "Skipping resource: #{out}"
93
+ end
94
+
95
+ result = cmd.stdout.delete(" ").gsub(/\n/, ",").gsub(/\r/, "").downcase
96
+ @data = Hash[result.scan(/([^:]+):([^,]+)[,$]/)]
97
+ end
98
+
99
+ def installed?
100
+ inspec.file(@path).exist?
101
+ end
102
+
103
+ def disabled?
104
+ @data["selinuxstatus"] == "disabled"
105
+ end
106
+
107
+ def enforcing?
108
+ @data["currentmode"] == "enforcing"
109
+ end
110
+
111
+ def permissive?
112
+ @data["currentmode"] == "permissive"
113
+ end
114
+
115
+ def policy
116
+ @data["loadedpolicyname"]
117
+ end
118
+
119
+ def modules
120
+ SelinuxModuleFilter.new(parse_modules)
121
+ end
122
+
123
+ def booleans
124
+ SelinuxBooleanFilter.new(parse_booleans)
125
+ end
126
+
127
+ def to_s
128
+ "SELinux"
129
+ end
130
+
131
+ private
132
+
133
+ def parse_modules
134
+ raw_modules = inspec.command("semodule -lfull").stdout
135
+ r_modules = []
136
+ raw_modules.each_line do |entry|
137
+ data = entry.split.map(&:strip)
138
+ state = data.length == 4 ? data[3] : "enabled"
139
+ r_modules.push({ name: data[1], status: "installed", state: state, priority: data[0] })
140
+ end
141
+ r_modules
142
+ end
143
+
144
+ def parse_booleans
145
+ raw_booleans = inspec.command("semanage boolean -l -n").stdout
146
+ r_booleans = []
147
+ raw_booleans.each_line do |entry|
148
+ data = entry.scan(/([^(,)]+)/).flatten.map(&:strip)
149
+ r_booleans.push({ name: data[0], state: data[1], default: data[2] })
150
+ end
151
+ r_booleans
152
+ end
153
+ end
154
+ end
data/lib/inspec/rule.rb CHANGED
@@ -180,7 +180,15 @@ module Inspec
180
180
  options[:priority] ||= 20
181
181
  options[:provider] = :inline_control_code
182
182
  evt = Inspec::Input.infer_event(options)
183
- Inspec::InputRegistry.find_or_register_input(input_name, __profile_id, event: evt).value
183
+ Inspec::InputRegistry.find_or_register_input(
184
+ input_name,
185
+ __profile_id,
186
+ type: options[:type],
187
+ required: options[:required],
188
+ description: options[:description],
189
+ pattern: options[:pattern],
190
+ event: evt
191
+ ).value
184
192
  end
185
193
  end
186
194
 
@@ -1,3 +1,3 @@
1
1
  module Inspec
2
- VERSION = "4.33.1".freeze
2
+ VERSION = "4.36.4".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inspec-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.33.1
4
+ version: 4.36.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chef InSpec Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-20 00:00:00.000000000 Z
11
+ date: 2021-04-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef-telemetry
@@ -223,7 +223,7 @@ dependencies:
223
223
  version: 0.9.0
224
224
  - - "<"
225
225
  - !ruby/object:Gem::Version
226
- version: '1.4'
226
+ version: '1.5'
227
227
  type: :runtime
228
228
  prerelease: false
229
229
  version_requirements: !ruby/object:Gem::Requirement
@@ -233,7 +233,7 @@ dependencies:
233
233
  version: 0.9.0
234
234
  - - "<"
235
235
  - !ruby/object:Gem::Version
236
- version: '1.4'
236
+ version: '1.5'
237
237
  - !ruby/object:Gem::Dependency
238
238
  name: faraday_middleware
239
239
  requirement: !ruby/object:Gem::Requirement
@@ -586,6 +586,7 @@ files:
586
586
  - lib/inspec/resources/script.rb
587
587
  - lib/inspec/resources/security_identifier.rb
588
588
  - lib/inspec/resources/security_policy.rb
589
+ - lib/inspec/resources/selinux.rb
589
590
  - lib/inspec/resources/service.rb
590
591
  - lib/inspec/resources/shadow.rb
591
592
  - lib/inspec/resources/ssh_config.rb