inspec-core 4.31.0 → 4.37.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: de259f902d4d891726e44204083a9fa2ab6b2b7507914036cc1af230e82dbc6b
4
- data.tar.gz: 16d2ce9dbe236411f8169b378c51bedd5e2fc87ee84429b14de8e7312f6576cd
3
+ metadata.gz: 65d5a9d62e8e76b31b944e42f4ae6fc1784e3823fa578ce8ee439a2270a80816
4
+ data.tar.gz: 1aa950d1012bd41e061cc58e5693003d9197749c3798d3fb7d50b434c33c13de
5
5
  SHA512:
6
- metadata.gz: 6f6646ab26611a0d49bce5bb8dd927ac678cb1ab032d5c5de055e5e769ef667f4147f4bae82613450c21c9ca0ebcd99302f33741ba51c95094b45714a6f69303
7
- data.tar.gz: c19721ef5d63cedae91fe69103f7f4ec4237ce4e16ab563895eff655b2ff32ec1ba15daf412cf23ed11966a9d94b5941b5c74ac6ba47c4c209f82a5db1240641
6
+ metadata.gz: 69e11bec35bfef9ccd66679c4c04a65afe7b8e2acb4f20ab1f2643ee594961148b269a21e4e84996053a5d18ae96120063f1cbfe634831488b8b830cb22b9942
7
+ data.tar.gz: 0476cf2df46ae81d3dd0a797d39190425ef28eeb7d8c36c3157d68d7ae658b1922f02251948fce8e5f2a48305f5c9e6ff520bc39a532e655b7f32284c7c67b46
data/Gemfile CHANGED
@@ -48,3 +48,16 @@ end
48
48
  group :deploy do
49
49
  gem "inquirer"
50
50
  end
51
+
52
+ # Only include Test Kitchen support if we are on Ruby 2.7 or higher
53
+ # as chef-zero support requires Ruby 2.6
54
+ # See https://github.com/inspec/inspec/pull/5341
55
+ if Gem.ruby_version >= Gem::Version.new("2.7.0")
56
+ group :kitchen do
57
+ gem "berkshelf"
58
+ gem "test-kitchen", ">= 2.8"
59
+ gem "kitchen-inspec", ">= 2.0"
60
+ gem "kitchen-dokken", ">= 2.11"
61
+ gem "git"
62
+ end
63
+ end
data/inspec-core.gemspec CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
23
23
  .reject { |f| File.directory?(f) }
24
24
 
25
25
  # Implementation dependencies
26
- spec.add_dependency "chef-telemetry", "~> 1.0"
26
+ spec.add_dependency "chef-telemetry", "~> 1.0", ">= 1.0.8" # 1.0.8+ removes the http dep
27
27
  spec.add_dependency "license-acceptance", ">= 0.2.13", "< 3.0"
28
28
  spec.add_dependency "thor", ">= 0.20", "< 2.0"
29
29
  spec.add_dependency "method_source", ">= 0.8", "< 2.0"
@@ -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"
@@ -168,9 +168,11 @@ module Inspec
168
168
  desc: "After normal execution order, results are sorted by control ID, or by file (default), or randomly. None uses legacy unsorted mode."
169
169
  option :filter_empty_profiles, type: :boolean, default: false,
170
170
  desc: "Filter empty profiles (profiles without controls) from the report."
171
- option :command_timeout, type: :numeric, default: 3600,
172
- desc: "Maximum seconds to allow commands to run during execution. Default 3600.",
173
- long_desc: "Maximum seconds to allow commands to run during execution. Default 3600. A timed out command is considered an error."
171
+ option :command_timeout, type: :numeric,
172
+ desc: "Maximum seconds to allow commands to run during execution.",
173
+ long_desc: "Maximum seconds to allow commands to run during execution. A timed out command is considered an error."
174
+ option :reporter_include_source, type: :boolean, default: false,
175
+ desc: "Include full source code of controls in the CLI report"
174
176
  end
175
177
 
176
178
  def self.help(*args)
data/lib/inspec/cli.rb CHANGED
@@ -218,9 +218,13 @@ class Inspec::InspecCLI < Inspec::BaseCLI
218
218
 
219
219
  Automate:
220
220
  ```
221
- #{Inspec::Dist::EXEC_NAME} compliance login
221
+ #{Inspec::Dist::EXEC_NAME} automate login
222
222
  #{Inspec::Dist::EXEC_NAME} exec compliance://username/linux-baseline
223
223
  ```
224
+ `inspec compliance` is a backwards compatible alias for `inspec automate` and works the same way:
225
+ ```
226
+ #{Inspec::Dist::EXEC_NAME} compliance login
227
+ ```
224
228
 
225
229
  Supermarket:
226
230
  ```
@@ -321,10 +325,14 @@ class Inspec::InspecCLI < Inspec::BaseCLI
321
325
  desc: "A space-delimited list of local folders containing profiles whose libraries and resources will be loaded into the new shell"
322
326
  option :distinct_exit, type: :boolean, default: true,
323
327
  desc: "Exit with code 100 if any tests fail, and 101 if any are skipped but none failed (default). If disabled, exit 0 on skips and 1 for failures."
324
- option :command_timeout, type: :numeric, default: 3600,
325
- desc: "Maximum seconds to allow a command to run. Default 3600.",
326
- long_desc: "Maximum seconds to allow commands to run. Default 3600. A timed out command is considered an error."
328
+ option :command_timeout, type: :numeric,
329
+ desc: "Maximum seconds to allow a command to run.",
330
+ long_desc: "Maximum seconds to allow commands to run. A timed out command is considered an error."
327
331
  option :inspect, type: :boolean, default: false, desc: "Use verbose/debugging output for resources."
332
+ option :input_file, type: :array,
333
+ desc: "Load one or more input files, a YAML file with values for the shell to use"
334
+ option :input, type: :array, banner: "name1=value1 name2=value2",
335
+ desc: "Specify one or more inputs directly on the command line to the shell, as --input NAME=VALUE. Accepts single-quoted YAML and JSON structures."
328
336
  def shell_func
329
337
  o = config
330
338
  diagnose(o)
@@ -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
 
@@ -117,6 +117,15 @@ module Inspec::Plugin::V2
117
117
  # `inspec dosomething` => activate the :dosomething hook
118
118
  activate_me ||= cli_args.include?(act.activator_name.to_s)
119
119
 
120
+ # Only one compliance command to be activated at one time.
121
+ # Since both commands are defined in the same class,
122
+ # activators were not getting fetched uniquely.
123
+ if cli_args.include?("automate") && act.activator_name.to_s.eql?("compliance")
124
+ activate_me = false
125
+ elsif cli_args.include?("compliance") && act.activator_name.to_s.eql?("automate")
126
+ activate_me = false
127
+ end
128
+
120
129
  # OK, activate.
121
130
  if activate_me
122
131
  act.activate
@@ -91,7 +91,7 @@ module Inspec
91
91
  end
92
92
 
93
93
  def all_controls
94
- ret = @rules.values
94
+ ret = @rules.values.compact
95
95
  ret += @control_subcontexts.map(&:all_rules).flatten
96
96
  ret
97
97
  end
@@ -41,12 +41,14 @@ module Inspec::Reporters
41
41
  MULTI_TEST_CONTROL_SUMMARY_MAX_LEN = 60
42
42
 
43
43
  def render
44
+ @src_extent_map = {}
44
45
  run_data[:profiles].each do |profile|
45
46
  if profile[:status] == "skipped"
46
47
  platform = run_data[:platform]
47
48
  output("Skipping profile: '#{profile[:name]}' on unsupported platform: '#{platform[:name]}/#{platform[:release]}'.")
48
49
  next
49
50
  end
51
+ read_control_source(profile)
50
52
  @control_count = 0
51
53
  output("")
52
54
  print_profile_header(profile)
@@ -89,6 +91,7 @@ module Inspec::Reporters
89
91
  next if control.results.nil?
90
92
 
91
93
  output(format_control_header(control))
94
+ output(format_control_source(control)) if Inspec::Config.cached[:reporter_include_source]
92
95
  control.results.each do |result|
93
96
  output(format_result(control, result, :standard))
94
97
  @control_count += 1
@@ -127,6 +130,62 @@ module Inspec::Reporters
127
130
  )
128
131
  end
129
132
 
133
+ def format_control_source(control)
134
+ src = @control_source[control.id]
135
+ message = "Control Source from #{src[:path]}:#{src[:start]}..#{src[:end]}\n"
136
+ message += src[:content]
137
+ format_message(
138
+ color: "skipped",
139
+ indentation: 5,
140
+ message: message
141
+ )
142
+ end
143
+
144
+ def read_control_source(profile)
145
+ return unless Inspec::Config.cached[:reporter_include_source]
146
+
147
+ @control_source = {}
148
+ src_extent_map = {}
149
+
150
+ # First pass: build map of paths => ids => [start]
151
+ all_unique_controls.each do |control|
152
+ id = control[:id]
153
+ path = control[:source_location][:ref]
154
+ start = control[:source_location][:line]
155
+ next if path.nil? || start.nil?
156
+
157
+ src_extent_map[path] ||= []
158
+ src_extent_map[path] << { start: start, id: id }
159
+ end
160
+
161
+ # Now sort the controls by their starting line in their control file
162
+ src_extent_map.values.each do |extent_list|
163
+ extent_list.sort! { |a, b| a[:start] <=> b[:start] }
164
+ end
165
+
166
+ # Third pass: Read in files and split into lines
167
+ src_extent_map.keys.each do |path|
168
+ control_file_lines = File.read(path).lines # TODO error handling
169
+ last_line_in_file = control_file_lines.count
170
+ extent_list = src_extent_map[path]
171
+ extent_list.each_with_index do |extent, idx|
172
+ if idx == extent_list.count - 1 # Last entry
173
+ extent[:end] = last_line_in_file
174
+ else
175
+ extent[:end] = extent_list[idx + 1][:start] - 1
176
+ end
177
+
178
+ @control_source[extent[:id]] =
179
+ {
180
+ path: path,
181
+ start: extent[:start],
182
+ end: extent[:end],
183
+ content: control_file_lines.slice(extent[:start] - 1, extent[:end] - extent[:start] + 1).join(""),
184
+ }
185
+ end
186
+ end
187
+ end
188
+
130
189
  def format_result(control, result, type)
131
190
  impact = control.impact_string_for_result(result)
132
191
 
@@ -312,6 +371,10 @@ module Inspec::Reporters
312
371
  data[:impact]
313
372
  end
314
373
 
374
+ def source_location
375
+ data[:source_location]
376
+ end
377
+
315
378
  def anonymous?
316
379
  id.start_with?("(generated from ")
317
380
  end
@@ -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"
@@ -31,16 +31,11 @@ module Inspec::Resources
31
31
  end
32
32
 
33
33
  @command = cmd
34
-
35
- cli_timeout = Inspec::Config.cached["command_timeout"].to_i
34
+ cli_timeout = Inspec::Config.cached["command_timeout"]&.to_i
36
35
  # Can access this via Inspec::InspecCLI.commands["exec"].options[:command_timeout].default,
37
36
  # but that may not be loaded for kitchen-inspec and other pure gem consumers
38
- default_cli_timeout = 3600
39
- if cli_timeout != default_cli_timeout
40
- @timeout = cli_timeout
41
- else
42
- @timeout = options[:timeout]&.to_i || default_cli_timeout
43
- end
37
+ cli_timeout = nil if cli_timeout == 0 # Under test-kitchen we get a 0 timeout, which can't be a resonable value
38
+ @timeout = cli_timeout || options[:timeout]&.to_i
44
39
 
45
40
  if options[:redact_regex]
46
41
  unless options[:redact_regex].is_a?(Regexp)
@@ -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
@@ -105,7 +105,7 @@ module Inspec::Resources
105
105
  # @see https://github.com/chef/chef/blob/master/lib/chef/resource/windows_firewall_rule.rb
106
106
  def load_firewall_state(rule_name)
107
107
  <<-EOH
108
- Remove-TypeData System.Array # workaround for PS bug here: https://bit.ly/2SRMQ8M
108
+ Get-TypeData -TypeName System.Array | Remove-TypeData # workaround for PS bug here: https://bit.ly/2SRMQ8M
109
109
  $rule = Get-NetFirewallRule -Name "#{rule_name}"
110
110
  $addressFilter = $rule | Get-NetFirewallAddressFilter
111
111
  $portFilter = $rule | Get-NetFirewallPortFilter
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.31.0".freeze
2
+ VERSION = "4.37.0".freeze
3
3
  end
@@ -6,24 +6,50 @@ This extensions offers the following features:
6
6
  - execute profiles directly from Chef Automate/Chef Compliance locally
7
7
  - upload a local profile to Chef Automate/Chef Compliance
8
8
 
9
+ `inspec compliance` is a backwards compatible alias for `inspec automate` and works the same way.
10
+
9
11
  To use the CLI, this InSpec add-on adds the following commands:
10
12
 
13
+ * `$ inspec automate login` - authentication of the API token against Chef Automate/Chef Compliance
14
+ * `$ inspec automate profiles` - list all available Compliance profiles
15
+ * `$ inspec exec compliance://profile` - runs a Compliance profile
16
+ * `$ inspec automate upload path/to/local/profile` - uploads a local profile to Chef Automate/Chef Compliance
17
+ * `$ inspec automate logout` - logout of Chef Automate/Chef Compliance
18
+
19
+ Similar to these CLI commands are:
20
+
11
21
  * `$ inspec compliance login` - authentication of the API token against Chef Automate/Chef Compliance
12
22
  * `$ inspec compliance profiles` - list all available Compliance profiles
13
- * `$ inspec exec compliance://profile` - runs a Compliance profile
14
23
  * `$ inspec compliance upload path/to/local/profile` - uploads a local profile to Chef Automate/Chef Compliance
15
24
  * `$ inspec compliance logout` - logout of Chef Automate/Chef Compliance
16
25
 
17
26
  Compliance profiles can be executed in two ways:
18
27
 
19
- - via compliance exec: `inspec compliance exec profile`
28
+ - via compliance exec: `inspec automate exec profile` or `inspec compliance exec profile`
20
29
  - via compliance scheme: `inspec exec compliance://profile`
21
30
 
22
31
 
32
+
33
+
23
34
  ## Usage
24
35
 
25
36
  ### Command options
26
37
 
38
+ ```
39
+ $ inspec automate
40
+ Commands:
41
+ inspec automate download PROFILE # downloads a profile from Chef Compliance
42
+ inspec automate exec PROFILE # executes a Chef Compliance profile
43
+ inspec automate help [COMMAND] # Describe subcommands or one specific subcommand
44
+ inspec automate login SERVER # Log in to a Chef Automate/Chef Compliance SERVER
45
+ inspec automate logout # user logout from Chef Compliance
46
+ inspec automate profiles # list all available profiles in Chef Compliance
47
+ inspec automate upload PATH # uploads a local profile to Chef Compliance
48
+ inspec automate version # displays the version of the Chef Compliance server
49
+ ```
50
+
51
+ or
52
+
27
53
  ```
28
54
  $ inspec compliance
29
55
  Commands:
@@ -41,6 +67,12 @@ Commands:
41
67
 
42
68
  You will need an API token for authentication. You can retrieve one via the admin section of your A2 web gui.
43
69
 
70
+ ```
71
+ $ inspec automate login https://automate2.compliance.test --insecure --user 'admin' --token 'zuop..._KzE'
72
+ ```
73
+
74
+ or
75
+
44
76
  ```
45
77
  $ inspec compliance login https://automate2.compliance.test --insecure --user 'admin' --token 'zuop..._KzE'
46
78
  ```
@@ -63,6 +95,12 @@ Example:
63
95
 
64
96
  You will need an access token for authentication. You can retrieve one via [UI](https://docs.chef.io/api_delivery.html) or [CLI](https://docs.chef.io/ctl_delivery.html#delivery-token).
65
97
 
98
+ ```
99
+ $ inspec automate login https://automate.compliance.test --insecure --user 'admin' --ent 'brewinc' --token 'zuop..._KzE'
100
+ ```
101
+
102
+ or
103
+
66
104
  ```
67
105
  $ inspec compliance login https://automate.compliance.test --insecure --user 'admin' --ent 'brewinc' --token 'zuop..._KzE'
68
106
  ```
@@ -75,12 +113,42 @@ You will need an access token for authentication. You can retrieve one via:
75
113
 
76
114
  You can choose the access token (`--token`) or the refresh token (`--refresh_token`)
77
115
 
116
+ ```
117
+ $ inspec automate login https://compliance.test --user admin --insecure --token '...'
118
+ ```
119
+
120
+ or
121
+
78
122
  ```
79
123
  $ inspec compliance login https://compliance.test --user admin --insecure --token '...'
80
124
  ```
81
125
 
82
126
  ### List available profiles via Chef Compliance / Automate
83
127
 
128
+ ```
129
+ $ inspec automate profiles
130
+ Available profiles:
131
+ -------------------
132
+ * base/apache
133
+ * base/linux
134
+ * base/mysql
135
+ * base/postgres
136
+ * base/ssh
137
+ * base/windows
138
+ * cis/cis-centos6-level1
139
+ * cis/cis-centos6-level2
140
+ * cis/cis-centos7-level1
141
+ * cis/cis-centos7-level2
142
+ * cis/cis-rhel7-level1
143
+ * cis/cis-rhel7-level2
144
+ * cis/cis-ubuntu12.04lts-level1
145
+ * cis/cis-ubuntu12.04lts-level2
146
+ * cis/cis-ubuntu14.04lts-level1
147
+ * cis/cis-ubuntu14.04lts-level2
148
+ ```
149
+
150
+ or
151
+
84
152
  ```
85
153
  $ inspec compliance profiles
86
154
  Available profiles:
@@ -105,6 +173,47 @@ Available profiles:
105
173
 
106
174
  ### Upload a profile to Chef Compliance / Automate
107
175
 
176
+ ```
177
+ $ inspec automate version
178
+ Chef Compliance version: 1.0.11
179
+ ➜ inspec git:(chris-rock/cc-error-not-loggedin) ✗ b inspec automate upload examples/profile
180
+ I, [2016-05-06T14:27:20.907547 #37592] INFO -- : Checking profile in examples/profile
181
+ I, [2016-05-06T14:27:20.907668 #37592] INFO -- : Metadata OK.
182
+ I, [2016-05-06T14:27:20.968584 #37592] INFO -- : Found 4 controls.
183
+ I, [2016-05-06T14:27:20.968638 #37592] INFO -- : Control definitions OK.
184
+ Profile is valid
185
+ Generate temporary profile archive at /var/folders/jy/2bnrfb4s36jbjtzllvhhyqhw0000gn/T/profile20160506-37592-1tf326f.tar.gz
186
+ I, [2016-05-06T14:27:21.020017 #37592] INFO -- : Generate archive /var/folders/jy/2bnrfb4s36jbjtzllvhhyqhw0000gn/T/profile20160506-37592-1tf326f.tar.gz.
187
+ I, [2016-05-06T14:27:21.024837 #37592] INFO -- : Finished archive generation.
188
+ Start upload to admin/profile
189
+ Uploading to Chef Compliance
190
+ Successfully uploaded profile
191
+
192
+ # display all profiles
193
+ $ inspec automate profiles
194
+ Available profiles:
195
+ -------------------
196
+ * admin/profile
197
+ * base/apache
198
+ * base/linux
199
+ * base/mysql
200
+ * base/postgres
201
+ * base/ssh
202
+ * base/windows
203
+ * cis/cis-centos6-level1
204
+ * cis/cis-centos6-level2
205
+ * cis/cis-centos7-level1
206
+ * cis/cis-centos7-level2
207
+ * cis/cis-rhel7-level1
208
+ * cis/cis-rhel7-level2
209
+ * cis/cis-ubuntu12.04lts-level1
210
+ * cis/cis-ubuntu12.04lts-level2
211
+ * cis/cis-ubuntu14.04lts-level1
212
+ * cis/cis-ubuntu14.04lts-level2
213
+ ```
214
+
215
+ or
216
+
108
217
  ```
109
218
  $ inspec compliance version
110
219
  Chef Compliance version: 1.0.11
@@ -168,17 +277,31 @@ $ inspec exec compliance://admin/apache-baseline#2.0.1
168
277
  ```
169
278
 
170
279
  Download a specific version(2.0.2) of a profile when logged in with Automate:
280
+ ```
281
+ $ inspec automate download compliance://admin/apache-baseline#2.0.2
282
+ ```
283
+
284
+ or
285
+
171
286
  ```
172
287
  $ inspec compliance download compliance://admin/apache-baseline#2.0.2
173
288
  ```
174
289
 
175
290
  ### To Logout from Chef Compliance
176
291
 
292
+ ```
293
+ $ inspec automate logout
294
+ Successfully logged out
295
+ ```
296
+
297
+ or
298
+
177
299
  ```
178
300
  $ inspec compliance logout
179
301
  Successfully logged out
180
302
  ```
181
303
 
304
+
182
305
  ## Integration Tests
183
306
 
184
307
  At this point of time, InSpec is not able to pick up the token directly, therefore the integration test is semi-automatic at this point of time:
@@ -7,6 +7,11 @@ module InspecPlugins
7
7
  require_relative "inspec-compliance/cli"
8
8
  InspecPlugins::Compliance::CLI
9
9
  end
10
+
11
+ cli_command :automate do
12
+ require_relative "inspec-compliance/cli"
13
+ InspecPlugins::Compliance::CLI
14
+ end
10
15
  end
11
16
 
12
17
  autoload :Configuration, "plugins/inspec-compliance/lib/inspec-compliance/configuration"
@@ -357,7 +357,7 @@ module InspecPlugins
357
357
 
358
358
  Inspec::Log.debug(
359
359
  "Received 200 from #{url}#{compliance_endpoint} - " \
360
- "assuming target is a #{COMPLIANCE_PRODUCT_NAME} server"
360
+ "assuming target is a #{AUTOMATE_PRODUCT_NAME} server"
361
361
  )
362
362
  true
363
363
  end
@@ -9,7 +9,7 @@ module InspecPlugins
9
9
  class CannotDetermineServerType < StandardError; end
10
10
 
11
11
  def login(options)
12
- raise ArgumentError, "Please specify a server using `#{EXEC_NAME} compliance login https://SERVER`" unless options["server"]
12
+ raise ArgumentError, "Please specify a server using `#{EXEC_NAME} automate login https://SERVER` or `#{EXEC_NAME} compliance login https://SERVER`" unless options["server"]
13
13
 
14
14
  options["server"] = URI("https://#{options["server"]}").to_s if URI(options["server"]).scheme.nil?
15
15
 
@@ -179,7 +179,7 @@ module InspecPlugins
179
179
  def self.compliance_verify_thor_options(o)
180
180
  error_msg = []
181
181
 
182
- error_msg.push("Please specify a server using `#{EXEC_NAME} compliance login https://SERVER`") if o["server"].nil?
182
+ error_msg.push("Please specify a server using `#{EXEC_NAME} automate login https://SERVER` or `#{EXEC_NAME} compliance login https://SERVER`") if o["server"].nil?
183
183
 
184
184
  if o["user"].nil? && o["refresh_token"].nil?
185
185
  error_msg.push("Please specify a `--user='USER'` or a `--refresh-token='TOKEN'`")
@@ -6,13 +6,12 @@ module InspecPlugins
6
6
  module Compliance
7
7
  class CLI < Inspec.plugin(2, :cli_command)
8
8
  include Inspec::Dist
9
-
10
- subcommand_desc "compliance SUBCOMMAND", "#{COMPLIANCE_PRODUCT_NAME} commands"
9
+ subcommand_desc "automate SUBCOMMAND or compliance SUBCOMMAND", "#{AUTOMATE_PRODUCT_NAME} commands"
11
10
 
12
11
  # desc "login https://SERVER --insecure --user='USER' --ent='ENTERPRISE' --token='TOKEN'", 'Log in to a Chef Compliance/Chef Automate SERVER'
13
- desc "login", "Log in to a #{COMPLIANCE_PRODUCT_NAME}/#{AUTOMATE_PRODUCT_NAME} SERVER"
12
+ desc "login", "Log in to a #{AUTOMATE_PRODUCT_NAME} SERVER"
14
13
  long_desc <<-LONGDESC
15
- `login` allows you to use InSpec with #{AUTOMATE_PRODUCT_NAME} or a #{COMPLIANCE_PRODUCT_NAME} Server
14
+ `login` allows you to use InSpec with #{AUTOMATE_PRODUCT_NAME} Server
16
15
 
17
16
  You need to a token for communication. More information about token retrieval
18
17
  is available at:
@@ -24,11 +23,11 @@ module InspecPlugins
24
23
  option :user, type: :string, required: false,
25
24
  desc: "Username"
26
25
  option :password, type: :string, required: false,
27
- desc: "Password (#{COMPLIANCE_PRODUCT_NAME} Only)"
26
+ desc: "Password (#{AUTOMATE_PRODUCT_NAME} Only)"
28
27
  option :token, type: :string, required: false,
29
28
  desc: "Access token"
30
29
  option :refresh_token, type: :string, required: false,
31
- desc: "#{COMPLIANCE_PRODUCT_NAME} refresh token (#{COMPLIANCE_PRODUCT_NAME} Only)"
30
+ desc: "#{AUTOMATE_PRODUCT_NAME} refresh token (#{AUTOMATE_PRODUCT_NAME} Only)"
32
31
  option :dctoken, type: :string, required: false,
33
32
  desc: "Data Collector token (#{AUTOMATE_PRODUCT_NAME} Only)"
34
33
  option :ent, type: :string, required: false,
@@ -40,7 +39,7 @@ module InspecPlugins
40
39
  puts "Stored configuration for Chef #{config["server_type"].capitalize}: #{config["server"]}' with user: '#{config["user"]}'"
41
40
  end
42
41
 
43
- desc "profiles", "list all available profiles in #{COMPLIANCE_PRODUCT_NAME}"
42
+ desc "profiles", "list all available profiles in #{AUTOMATE_PRODUCT_NAME}"
44
43
  option :owner, type: :string, required: false,
45
44
  desc: "owner whose profiles to list"
46
45
  def profiles
@@ -65,11 +64,11 @@ module InspecPlugins
65
64
  exit 1
66
65
  end
67
66
  rescue InspecPlugins::Compliance::ServerConfigurationMissing
68
- $stderr.puts "\nServer configuration information is missing. Please login using `#{EXEC_NAME} compliance login`"
67
+ $stderr.puts "\nServer configuration information is missing. Please login using `#{EXEC_NAME} #{subcommand_name} login`"
69
68
  exit 1
70
69
  end
71
70
 
72
- desc "exec PROFILE", "executes a #{COMPLIANCE_PRODUCT_NAME} profile"
71
+ desc "exec PROFILE", "executes a #{AUTOMATE_PRODUCT_NAME} profile"
73
72
  exec_options
74
73
  def exec(*tests)
75
74
  compliance_config = InspecPlugins::Compliance::Configuration.new
@@ -91,7 +90,7 @@ module InspecPlugins
91
90
  exit 1
92
91
  end
93
92
 
94
- desc "download PROFILE", "downloads a profile from #{COMPLIANCE_PRODUCT_NAME}"
93
+ desc "download PROFILE", "downloads a profile from #{AUTOMATE_PRODUCT_NAME}"
95
94
  option :name, type: :string,
96
95
  desc: "Name of the archive filename (file type will be added)"
97
96
  def download(profile_name)
@@ -116,12 +115,12 @@ module InspecPlugins
116
115
  file_name = fetcher.fetch(o.name || id)
117
116
  puts "Profile stored to #{file_name}"
118
117
  else
119
- puts "Profile #{profile_name} is not available in #{COMPLIANCE_PRODUCT_NAME}."
118
+ puts "Profile #{profile_name} is not available in #{AUTOMATE_PRODUCT_NAME}."
120
119
  exit 1
121
120
  end
122
121
  end
123
122
 
124
- desc "upload PATH", "uploads a local profile to #{COMPLIANCE_PRODUCT_NAME}"
123
+ desc "upload PATH", "uploads a local profile to #{AUTOMATE_PRODUCT_NAME}"
125
124
  option :overwrite, type: :boolean, default: false,
126
125
  desc: "Overwrite existing profile on Server."
127
126
  option :owner, type: :string, required: false,
@@ -167,7 +166,7 @@ module InspecPlugins
167
166
 
168
167
  # determine user information
169
168
  if (config["token"].nil? && config["refresh_token"].nil?) || config["user"].nil?
170
- error.call("Please login via `#{EXEC_NAME} compliance login`")
169
+ error.call("Please login via `#{EXEC_NAME} #{subcommand_name} login`")
171
170
  end
172
171
 
173
172
  # read profile name from inspec.yml
@@ -202,11 +201,8 @@ module InspecPlugins
202
201
  puts "Start upload to #{config["owner"]}/#{profile_name}"
203
202
  pname = ERB::Util.url_encode(profile_name)
204
203
 
205
- if InspecPlugins::Compliance::API.is_automate_server?(config) || InspecPlugins::Compliance::API.is_automate2_server?(config)
206
- puts "Uploading to #{AUTOMATE_PRODUCT_NAME}"
207
- else
208
- puts "Uploading to #{COMPLIANCE_PRODUCT_NAME}"
209
- end
204
+ puts "Uploading to #{AUTOMATE_PRODUCT_NAME}"
205
+
210
206
  success, msg = InspecPlugins::Compliance::API.upload(config, config["owner"], pname, archive_path)
211
207
 
212
208
  # delete temp file if it was temporary generated
@@ -221,7 +217,7 @@ module InspecPlugins
221
217
  end
222
218
  end
223
219
 
224
- desc "version", "displays the version of the #{COMPLIANCE_PRODUCT_NAME} server"
220
+ desc "version", "displays the version of the #{AUTOMATE_PRODUCT_NAME} server"
225
221
  def version
226
222
  config = InspecPlugins::Compliance::Configuration.new
227
223
  info = InspecPlugins::Compliance::API.version(config)
@@ -233,11 +229,11 @@ module InspecPlugins
233
229
  exit 1
234
230
  end
235
231
  rescue InspecPlugins::Compliance::ServerConfigurationMissing
236
- puts "\nServer configuration information is missing. Please login using `#{EXEC_NAME} compliance login`"
232
+ puts "\nServer configuration information is missing. Please login using `#{EXEC_NAME} #{subcommand_name} login`"
237
233
  exit 1
238
234
  end
239
235
 
240
- desc "logout", "user logout from #{COMPLIANCE_PRODUCT_NAME}"
236
+ desc "logout", "user logout from #{AUTOMATE_PRODUCT_NAME}"
241
237
  def logout
242
238
  config = InspecPlugins::Compliance::Configuration.new
243
239
  unless config.supported?(:oidc) || config["token"].nil? || config["server_type"] == "automate"
@@ -258,9 +254,13 @@ module InspecPlugins
258
254
 
259
255
  def loggedin(config)
260
256
  serverknown = !config["server"].nil?
261
- puts "You need to login first with `#{EXEC_NAME} compliance login`" unless serverknown
257
+ puts "You need to login first with `#{EXEC_NAME} #{subcommand_name} login`" unless serverknown
262
258
  serverknown
263
259
  end
260
+
261
+ def subcommand_name
262
+ @_invocations[Inspec::InspecCLI]&.first || "automate"
263
+ end
264
264
  end
265
265
 
266
266
  # register the subcommand to InSpec CLI registry
@@ -34,13 +34,13 @@ module InspecPlugins
34
34
  if config["token"].nil? && config["refresh_token"].nil?
35
35
  if config["server_type"] == "automate"
36
36
  server = "automate"
37
- msg = "#{EXEC_NAME} compliance login https://your_automate_server --user USER --ent ENT --dctoken DCTOKEN or --token USERTOKEN"
37
+ msg = "#{EXEC_NAME} [automate|compliance] login https://your_automate_server --user USER --ent ENT --dctoken DCTOKEN or --token USERTOKEN"
38
38
  elsif config["server_type"] == "automate2"
39
39
  server = "automate2"
40
- msg = "#{EXEC_NAME} compliance login https://your_automate2_server --user USER --token APITOKEN"
40
+ msg = "#{EXEC_NAME} [automate|compliance] login https://your_automate2_server --user USER --token APITOKEN"
41
41
  else
42
42
  server = "compliance"
43
- msg = "#{EXEC_NAME} compliance login https://your_compliance_server --user admin --insecure --token 'PASTE TOKEN HERE' "
43
+ msg = "#{EXEC_NAME} [automate|compliance] login https://your_compliance_server --user admin --insecure --token 'PASTE TOKEN HERE' "
44
44
  end
45
45
  raise Inspec::FetcherFailure, <<~EOF
46
46
 
@@ -112,7 +112,7 @@ module InspecPlugins
112
112
  end
113
113
 
114
114
  def to_s
115
- "#{COMPLIANCE_PRODUCT_NAME} Profile Loader"
115
+ "#{AUTOMATE_PRODUCT_NAME} Profile Loader"
116
116
  end
117
117
 
118
118
  private
@@ -136,6 +136,7 @@ module InspecPlugins
136
136
  if m.nil?
137
137
  raise "Unable to determine compliance profile name. This can be caused by " \
138
138
  "an incorrect server in your configuration. Try to login to compliance " \
139
+ "via the `#{EXEC_NAME} automate login` command or " \
139
140
  "via the `#{EXEC_NAME} compliance login` command."
140
141
  end
141
142
 
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.31.0
4
+ version: 4.37.0
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-07 00:00:00.000000000 Z
11
+ date: 2021-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef-telemetry
@@ -17,6 +17,9 @@ dependencies:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.0.8
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -24,6 +27,9 @@ dependencies:
24
27
  - - "~>"
25
28
  - !ruby/object:Gem::Version
26
29
  version: '1.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.0.8
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: license-acceptance
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -223,7 +229,7 @@ dependencies:
223
229
  version: 0.9.0
224
230
  - - "<"
225
231
  - !ruby/object:Gem::Version
226
- version: '1.4'
232
+ version: '1.5'
227
233
  type: :runtime
228
234
  prerelease: false
229
235
  version_requirements: !ruby/object:Gem::Requirement
@@ -233,7 +239,7 @@ dependencies:
233
239
  version: 0.9.0
234
240
  - - "<"
235
241
  - !ruby/object:Gem::Version
236
- version: '1.4'
242
+ version: '1.5'
237
243
  - !ruby/object:Gem::Dependency
238
244
  name: faraday_middleware
239
245
  requirement: !ruby/object:Gem::Requirement
@@ -586,6 +592,7 @@ files:
586
592
  - lib/inspec/resources/script.rb
587
593
  - lib/inspec/resources/security_identifier.rb
588
594
  - lib/inspec/resources/security_policy.rb
595
+ - lib/inspec/resources/selinux.rb
589
596
  - lib/inspec/resources/service.rb
590
597
  - lib/inspec/resources/shadow.rb
591
598
  - lib/inspec/resources/ssh_config.rb