inspec-core 2.2.35 → 2.2.41

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.
data/docs/reporters.md CHANGED
@@ -116,12 +116,12 @@ This reporter includes all information from the rspec runner. Unlike the json re
116
116
 
117
117
  This renders html code to view your tests in a browser. It includes all the test and summary information.
118
118
 
119
-
120
119
  ## Automate Reporter
121
120
 
122
121
  The automate reporter type is a special reporter used with the Automate 2 suite. To use this reporter you must pass in the correct configuration via a json config `--json-config`.
123
122
 
124
123
  Example config:
124
+
125
125
  ```json
126
126
  "reporter": {
127
127
  "automate" : {
@@ -135,27 +135,36 @@ Example config:
135
135
  }
136
136
  ```
137
137
 
138
- ### Mandatory fields:
138
+ ### Mandatory fields
139
+
139
140
  #### stdout
141
+
140
142
  This will either suppress or show the automate report in the CLI screen on completion
141
143
 
142
144
  #### url
145
+
143
146
  This is your Automate 2 url. Append `data-collector/v0/` at the end.
144
147
 
145
148
  #### token
149
+
146
150
  This is your Automate 2 token. You can generate this token by navigating to the admin tab of A2 and then api keys.
147
151
 
148
152
  ### Optional fields
153
+
149
154
  #### insecure
155
+
150
156
  This will disable or enable the ssl check when accessing the Automate 2 instance.
151
157
 
152
- PLEASE NOTE: These fields are ONLY needed if you do not have chef-client attached to a chef server running on your node. The fields below will be automaticlly pulled from the chef server.
158
+ PLEASE NOTE: These fields are ONLY needed if you do not have chef-client attached to a chef server running on your node. The fields below will be automatically pulled from the chef server.
153
159
 
154
160
  #### node_name
161
+
155
162
  This will be the node name which shows up in Automate 2.
156
163
 
157
164
  #### node_uuid
165
+
158
166
  This overrides the node uuid sent up to Automate 2. On non-chef nodes we will try to generate a static node uuid for you from your hardware. This will almost never be needed unless your working with a unique virtual setup.
159
167
 
160
168
  #### environment
161
- This will set the enviroment metadata for Automate 2.
169
+
170
+ This will set the environment metadata for Automate 2.
@@ -124,6 +124,34 @@ Wix includes several tools -- such as `candle` (preprocesses and compiles source
124
124
  end
125
125
  end
126
126
 
127
+ ### Redacting Sensitive Commands
128
+
129
+ By default the command that is ran is shown in the InSpec output. This can be problematic if the command contains sensitive arguments such as a password. These sensitive parts can be redacted by passing in `redact_regex` and a regular expression to redact. Optionally, you can use 2 capture groups to fine tune what is redacted.
130
+
131
+ The following examples show how to use `redact_regex`:
132
+
133
+ # Example without capture groups
134
+ describe command('myapp -p secretpassword -d no_redact', redact_regex: /-p .* -d/) do
135
+ its('exit_status') { should cmp 0 }
136
+ end
137
+
138
+ # Result (no capture groups used)
139
+ Command: `myapp REDACTED no_redact`
140
+ ✔ exit_status should cmp == 0
141
+
142
+ # Example with capture groups
143
+ # Each set of parenthesis is a capture group.
144
+ # Anything in the two capture groups will not be 'REDACTED'
145
+ describe command('myapp -p secretpassword -d no_redact', redact_regex: /(-p ).*( -d)/) do
146
+ its('exit_status') { should cmp 0 }
147
+ end
148
+
149
+ # Result (capture groups used)
150
+ Command: `myapp -p REDACTED -d no_redact`
151
+ ✔ exit_status should cmp == 0
152
+
153
+ > For more info/help on regular expressions, we recommend [RegExr](https://regexr.com/)
154
+
127
155
  <br>
128
156
 
129
157
  ## Matchers
@@ -149,10 +149,13 @@ The `name` matcher tests the value for the specified registry setting:
149
149
 
150
150
 
151
151
  <p class="warning">
152
- Any name with a dot will not work as expected: <code>its('explorer.exe') { should eq 'test' }</code>. This issue is tracked in <a href="https://github.com/chef/inspec/issues/1281">https://github.com/chef/inspec/issues/1281</a>
152
+ Any name with a dot will not work as expected: <code>its('explorer.exe') { should eq 'test' }</code>. For details, see <a href="https://github.com/inspec/inspec/issues/1281">https://github.com/inspec/inspec/issues/1281</a>
153
153
  </p>
154
154
 
155
155
  # instead of:
156
156
  # its('explorer.exe') { should eq 'test' }
157
- # use the following solution:
157
+ # either use have_property_value...
158
158
  it { should have_property_value('explorer.exe', :string, 'test') }
159
+
160
+ # ...or provide the parts of the dot-separated name in an array
161
+ its(['explorer', 'exe']) { should eq 'test' }
@@ -13,7 +13,7 @@ Use the `xinetd_conf` InSpec audit resource to test services under `/etc/xinet.d
13
13
 
14
14
  An `xinetd_conf` resource block declares settings found in a `xinetd.conf` file for the named service:
15
15
 
16
- describe xinetd_conf('service_name') do
16
+ describe xinetd_conf.services('service_name') do
17
17
  it { should be_enabled } # or be_disabled
18
18
  its('setting') { should eq 'value' }
19
19
  end
data/docs/ruby_usage.md CHANGED
@@ -61,7 +61,6 @@ to process the output of `ls` executed on the target system, use
61
61
  Similarly, use `inspec.file(PATH)` to access files or directories from
62
62
  remote systems in your tests or custom resources.
63
63
 
64
-
65
64
  ## Using rubygems
66
65
 
67
66
  Ruby gems are self-contained programs and libraries. If you create a custom
@@ -158,7 +157,8 @@ When writing tests you can not use standard ruby methods to shellout as it tries
158
157
  However, the `command` resource has a `.stdout` method that will allow you to manipulate the results.
159
158
  Using the above example, you could check the writes on several subdirectories.
160
159
 
161
- ### Example 1:
160
+ ### Example 1
161
+
162
162
  ```ruby
163
163
  $ inspec shell
164
164
  Welcome to the interactive InSpec Shell
@@ -179,7 +179,8 @@ Version: (not specified)
179
179
  Test Summary: 1 successful, 0 failures, 0 skipped
180
180
  ```
181
181
 
182
- ### Example 2:
182
+ ### Example 2
183
+
183
184
  ```ruby
184
185
  $ inspec shell
185
186
  Welcome to the interactive InSpec Shell
@@ -5,4 +5,8 @@
5
5
  libdir = File.dirname(__FILE__)
6
6
  $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
7
7
 
8
+ module Init
9
+ autoload :Profile, 'inspec-init/profile'
10
+ end
11
+
8
12
  require 'inspec-init/cli'
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'pathname'
4
+ require_relative 'renderer'
4
5
 
5
6
  module Init
6
7
  class CLI < Inspec::BaseCLI
@@ -15,85 +16,21 @@ module Init
15
16
  namespace
16
17
  end
17
18
 
18
- # read template directoy
19
+ # Look in the 'template' directory, and register a subcommand
20
+ # for each template directory found there.
19
21
  template_dir = File.join(File.dirname(__FILE__), 'templates')
20
22
  Dir.glob(File.join(template_dir, '*')) do |template|
21
- relative = Pathname.new(template).relative_path_from(Pathname.new(template_dir))
23
+ template_name = Pathname.new(template).relative_path_from(Pathname.new(template_dir)).to_s
22
24
 
23
25
  # register command for the template
24
- desc "#{relative} NAME", "Create a new #{relative}"
26
+ desc "#{template_name} NAME", "Create a new #{template_name}"
25
27
  option :overwrite, type: :boolean, default: false,
26
- desc: 'Overwrites existing directory'
27
- define_method relative.to_s.to_sym do |name|
28
- generator(relative.to_s, { name: name }, options)
28
+ desc: 'Overwrites existing directory'
29
+ define_method template_name.to_sym do |name_for_new_structure|
30
+ renderer = Init::Renderer.new(self, options)
31
+ renderer.render_with_values(template_name, name: name_for_new_structure)
29
32
  end
30
33
  end
31
-
32
- private
33
-
34
- # 1. iterate over all files
35
- # 2. read content in erb
36
- # 3. write to target
37
- def generator(type, attributes = {}, options = {}) # rubocop:disable Metrics/AbcSize
38
- # path of this script
39
- dir = File.dirname(__FILE__)
40
- # look for template directory
41
- base_dir = File.join(dir, 'templates', type)
42
- # prepare glob for all subdirectories and files
43
- template = File.join(base_dir, '**', '{*,.*}')
44
- # Use the name attribute to define the path to the profile.
45
- profile_path = attributes[:name]
46
- # Use slashes (\, /) to split up the name into an Array then use the last entry
47
- # to reset the name of the profile.
48
- attributes[:name] = attributes[:name].split(%r{\\|\/}).last
49
- # Generate the full target path on disk
50
- target = Pathname.new(Dir.pwd).join(profile_path)
51
- puts "Create new #{type} at #{mark_text(target)}"
52
-
53
- # check that the directory does not exist
54
- if File.exist?(target) && !options['overwrite']
55
- error "#{mark_text(target)} exists already, use --overwrite"
56
- exit 1
57
- end
58
-
59
- # ensure that target directory is available
60
- FileUtils.mkdir_p(target)
61
-
62
- # iterate over files and write to target path
63
- Dir.glob(template) do |file|
64
- relative = Pathname.new(file).relative_path_from(Pathname.new(base_dir))
65
- destination = Pathname.new(target).join(relative)
66
- if File.directory?(file)
67
- li "Create directory #{mark_text(relative)}"
68
- FileUtils.mkdir_p(destination)
69
- elsif File.file?(file)
70
- li "Create file #{mark_text(relative)}"
71
- # read & render content
72
- content = render(File.read(file), attributes)
73
- # write file content
74
- File.write(destination, content)
75
- else
76
- puts "Ignore #{file}, because its not an file or directoy"
77
- end
78
- end
79
- end
80
-
81
- # This is a render helper to bind hash values to a ERB template
82
- def render(content, hash)
83
- # create a new binding class
84
- cls = Class.new do
85
- hash.each do |key, value|
86
- define_method key.to_sym do
87
- value
88
- end
89
- end
90
- # expose binding
91
- define_method :bind do
92
- binding
93
- end
94
- end
95
- ERB.new(content).result(cls.new.bind)
96
- end
97
34
  end
98
35
 
99
36
  # register the subcommand to Inspec CLI registry
@@ -0,0 +1,79 @@
1
+ require 'fileutils'
2
+ require 'erb'
3
+
4
+ module Init
5
+ class Renderer
6
+ # Creates a renderer able to render the given template type
7
+ # 1. iterate over all files
8
+ # 2. read content in erb
9
+ # 3. write to full_destination_root_path
10
+
11
+ attr_reader :overwrite_mode, :ui
12
+ def initialize(cli_ui, cli_options = {})
13
+ @ui = cli_ui
14
+ @overwrite_mode = cli_options['overwrite']
15
+ end
16
+
17
+ # rubocop: disable Metrics/AbcSize
18
+ def render_with_values(template_type, template_values = {})
19
+ # look for template directory
20
+ base_dir = File.join(File.dirname(__FILE__), 'templates', template_type)
21
+ # prepare glob for all subdirectories and files
22
+ template_glob = File.join(base_dir, '**', '{*,.*}')
23
+ # Use the name attribute to define the path to the profile.
24
+ profile_path = template_values[:name]
25
+ # Use slashes (\, /) to split up the name into an Array then use the last entry
26
+ # to reset the name of the profile.
27
+ template_values[:name] = template_values[:name].split(%r{\\|\/}).last
28
+ # Generate the full full_destination_root_path path on disk
29
+ full_destination_root_path = Pathname.new(Dir.pwd).join(profile_path)
30
+ ui.plain_text "Create new #{template_type} at #{ui.mark_text(full_destination_root_path)}"
31
+
32
+ # check that the directory does not exist
33
+ if File.exist?(full_destination_root_path) && !overwrite_mode
34
+ ui.plain_text "#{ui.mark_text(full_destination_root_path)} exists already, use --overwrite"
35
+ ui.exit(1)
36
+ end
37
+
38
+ # ensure that full_destination_root_path directory is available
39
+ FileUtils.mkdir_p(full_destination_root_path)
40
+
41
+ # iterate over files and write to full_destination_root_path
42
+ Dir.glob(template_glob) do |file|
43
+ relative_destination_item_path = Pathname.new(file).relative_path_from(Pathname.new(base_dir))
44
+ full_destination_item_path = Pathname.new(full_destination_root_path).join(relative_destination_item_path)
45
+ if File.directory?(file)
46
+ ui.li "Create directory #{ui.mark_text(relative_destination_item_path)}"
47
+ FileUtils.mkdir_p(full_destination_item_path)
48
+ elsif File.file?(file)
49
+ ui.li "Create file #{ui.mark_text(relative_destination_item_path)}"
50
+ # read & render content
51
+ content = render(File.read(file), template_values)
52
+ # write file content
53
+ File.write(full_destination_item_path, content)
54
+ else
55
+ ui.plain_text "Ignore #{file}, because its not an file or directoy"
56
+ end
57
+ end
58
+ end
59
+ # rubocop: enable Metrics/AbcSize
60
+
61
+ # This is a render helper to bind hash values to a ERB template
62
+ # ERB provides result_with_hash in ruby 2.5.0+, which does exactly this
63
+ def render(template_content, hash)
64
+ # create a new binding class
65
+ cls = Class.new do
66
+ hash.each do |key, value|
67
+ define_method key.to_sym do
68
+ value
69
+ end
70
+ end
71
+ # expose binding
72
+ define_method :bind do
73
+ binding
74
+ end
75
+ end
76
+ ERB.new(template_content).result(cls.new.bind)
77
+ end
78
+ end
79
+ end
@@ -210,6 +210,31 @@ module Inspec
210
210
  str
211
211
  end
212
212
 
213
+ # These need to be public methods on any BaseCLI instance,
214
+ # but Thor interprets all methods as subcommands. The no_commands block
215
+ # treats them as regular methods.
216
+ no_commands do
217
+ def mark_text(text)
218
+ "\e[0;36m#{text}\e[0m"
219
+ end
220
+
221
+ def headline(title)
222
+ puts "\n== #{title}\n\n"
223
+ end
224
+
225
+ def li(entry)
226
+ puts " #{mark_text('*')} #{entry}"
227
+ end
228
+
229
+ def exit(code)
230
+ Kernel.exit code
231
+ end
232
+
233
+ def plain_text(msg)
234
+ puts msg
235
+ end
236
+ end
237
+
213
238
  private
214
239
 
215
240
  def suppress_log_output?(opts)
@@ -363,17 +388,5 @@ module Inspec
363
388
  end
364
389
  o[:logger].level = get_log_level(o.log_level)
365
390
  end
366
-
367
- def mark_text(text)
368
- "\e[0;36m#{text}\e[0m"
369
- end
370
-
371
- def headline(title)
372
- puts "\n== #{title}\n\n"
373
- end
374
-
375
- def li(entry)
376
- puts " #{mark_text('*')} #{entry}"
377
- end
378
391
  end
379
392
  end
@@ -11,7 +11,14 @@ module Inspec
11
11
  end
12
12
 
13
13
  def to_ruby
14
- itsy = its.nil? ? 'it' : 'its(' + its.to_s.inspect + ')'
14
+ itsy = 'it'
15
+ unless its.nil?
16
+ if its.is_a? Array
17
+ itsy = 'its(' + its.inspect + ')'
18
+ else
19
+ itsy = 'its(' + its.to_s.inspect + ')'
20
+ end
21
+ end
15
22
  naughty = negated ? '_not' : ''
16
23
  xpect = if expectation.nil?
17
24
  ''
@@ -90,8 +90,8 @@ module Inspec
90
90
 
91
91
  def check_supports
92
92
  status = inspec.platform.supported?(@supports)
93
- skip_msg = "Resource #{@__resource_name__.capitalize} is not supported on platform #{inspec.platform.name}/#{inspec.platform.release}."
94
- skip_resource(skip_msg) unless status
93
+ fail_msg = "Resource #{@__resource_name__.capitalize} is not supported on platform #{inspec.platform.name}/#{inspec.platform.release}."
94
+ fail_resource(fail_msg) unless status
95
95
  status
96
96
  end
97
97
 
@@ -4,5 +4,5 @@
4
4
  # author: Christoph Hartmann
5
5
 
6
6
  module Inspec
7
- VERSION = '2.2.35'
7
+ VERSION = '2.2.41'
8
8
  end
@@ -22,11 +22,22 @@ module Inspec::Resources
22
22
 
23
23
  attr_reader :command
24
24
 
25
- def initialize(cmd)
25
+ def initialize(cmd, options = {})
26
26
  if cmd.nil?
27
27
  raise 'InSpec `command` was called with `nil` as the argument. This is not supported. Please provide a valid command instead.'
28
28
  end
29
+
29
30
  @command = cmd
31
+
32
+ if options[:redact_regex]
33
+ unless options[:redact_regex].is_a?(Regexp)
34
+ # Make sure command is replaced so sensitive output isn't shown
35
+ @command = 'ERROR'
36
+ raise Inspec::Exceptions::ResourceFailed,
37
+ 'The `redact_regex` option must be a regular expression'
38
+ end
39
+ @redact_regex = options[:redact_regex]
40
+ end
30
41
  end
31
42
 
32
43
  def result
@@ -67,7 +78,11 @@ module Inspec::Resources
67
78
  end
68
79
 
69
80
  def to_s
70
- "Command #{@command}"
81
+ output = "Command: `#{@command}`"
82
+ # Redact output if the `redact_regex` option is passed
83
+ # If no capture groups are passed then `\1` and `\2` are ignored
84
+ output.gsub!(@redact_regex, '\1REDACTED\2') unless @redact_regex.nil?
85
+ output
71
86
  end
72
87
  end
73
88
  end