inspec 1.47.0 → 1.48.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 73d4de764766d6ce02f52597d9cdd3d3c5f962bf
4
- data.tar.gz: 0aaec0745ed380804d6bd333711054eab7c505ea
3
+ metadata.gz: '012308b85533b4379b4dae9b2d6bb956e4716dea'
4
+ data.tar.gz: a621d9a79814290988494ec07da9bad51057f33b
5
5
  SHA512:
6
- metadata.gz: 93d630d3408a4c34b13504dbdc6cb07e0de5a672525db739bb7e54eff8d0971b09838ae5c14169362d3a98b58ae27af1feffb0e443733e5e92ce948786494f95
7
- data.tar.gz: 49a27fd5dbe847483d31fa7d5ec357c91008596f47042d531c81c290b332b542d7caf90e56a9ae04c572b9d39cc913dda87565ec82a405aeef92e7c3d87df425
6
+ metadata.gz: 93b4c27033acdb1e4559c48940d0c73b1d94b3b20e109ed6a3b2ecf57908143b8c133717790ff273253aa580d893ee3ecd9a75e1129d9125bbc64f2c7c2d8397
7
+ data.tar.gz: 8eb7fe1e83c0bba17b5ef763015c83be4952c622e80a80af68a702d829d78bed389864157cdee86352f4ae166213ddc17b4fd5fbd5455719c89c8efc3de77a30
@@ -1,29 +1,47 @@
1
1
  # Change Log
2
2
  <!-- usage documentation: http://expeditor-docs.es.chef.io/configuration/changelog/ -->
3
- <!-- latest_release 1.47.0 -->
4
- ## [v1.47.0](https://github.com/chef/inspec/tree/v1.47.0) (2017-12-04)
3
+ <!-- latest_release 1.48.0 -->
4
+ ## [v1.48.0](https://github.com/chef/inspec/tree/v1.48.0) (2017-12-07)
5
5
 
6
- #### New Features
7
- - Enable caching for backend calls [#2309](https://github.com/chef/inspec/pull/2309) ([jquick](https://github.com/jquick))
6
+ #### Merged Pull Requests
7
+ - Fix changelog categories, bump minor version for release [#2381](https://github.com/chef/inspec/pull/2381) ([adamleff](https://github.com/adamleff))
8
8
  <!-- latest_release -->
9
9
 
10
- <!-- release_rollup since=1.46.2 -->
11
- ### Changes since 1.46.2 release
10
+ <!-- release_rollup since=1.47.0 -->
11
+ ### Changes since 1.47.0 release
12
12
 
13
- #### New Features
14
- - Enable caching for backend calls [#2309](https://github.com/chef/inspec/pull/2309) ([jquick](https://github.com/jquick)) <!-- 1.47.0 -->
13
+ #### Enhancements
14
+ - Allow crontab resource to read crontab at user specified paths. [#2328](https://github.com/chef/inspec/pull/2328) ([miah](https://github.com/miah)) <!-- 1.47.7 -->
15
+ - Update default cli options to be uniq per command type [#2378](https://github.com/chef/inspec/pull/2378) ([jquick](https://github.com/jquick)) <!-- 1.47.6 -->
16
+
17
+ #### Bug Fixes
18
+ - Allow `inspec check` to ignore `only_if` [#2250](https://github.com/chef/inspec/pull/2250) ([jerryaldrichiii](https://github.com/jerryaldrichiii)) <!-- 1.47.2 -->
19
+ - Remove rainbow dependency, fix duplicate rake gem [#2374](https://github.com/chef/inspec/pull/2374) ([adamleff](https://github.com/adamleff)) <!-- 1.47.8 -->
20
+ - Resolve merge issue with json-config vs thor defaults [#2377](https://github.com/chef/inspec/pull/2377) ([jquick](https://github.com/jquick)) <!-- 1.47.5 -->
21
+ - Update rspec cli control summary to not uniq fails/skips [#2362](https://github.com/chef/inspec/pull/2362) ([jquick](https://github.com/jquick)) <!-- 1.47.1 -->
15
22
 
16
23
  #### Merged Pull Requests
17
- - docker_image resource: properly handle registries in image strings [#2356](https://github.com/chef/inspec/pull/2356) ([adamleff](https://github.com/adamleff)) <!-- 1.46.5 -->
24
+ - Fix changelog categories, bump minor version for release [#2381](https://github.com/chef/inspec/pull/2381) ([adamleff](https://github.com/adamleff)) <!-- 1.48.0 -->
25
+ - Fix inspec appveyor test with the new local train transport [#2376](https://github.com/chef/inspec/pull/2376) ([jquick](https://github.com/jquick)) <!-- 1.47.4 -->
26
+ - Update command resource to check for mock backend [#2353](https://github.com/chef/inspec/pull/2353) ([jquick](https://github.com/jquick)) <!-- 1.47.3 -->
27
+ <!-- release_rollup -->
28
+
29
+ <!-- latest_stable_release -->
30
+ ## [v1.47.0](https://github.com/chef/inspec/tree/v1.47.0) (2017-12-04)
31
+
32
+ #### New Features
33
+ - Enable caching for backend calls [#2309](https://github.com/chef/inspec/pull/2309) ([jquick](https://github.com/jquick))
18
34
 
19
35
  #### Bug Fixes
20
- - security_policy resource: use PID for filename instead of random [#2368](https://github.com/chef/inspec/pull/2368) ([jquick](https://github.com/jquick)) <!-- 1.46.7 -->
21
- - key_rsa resource: fix inline shell documentation help, wrong resource name used in examples [#2364](https://github.com/chef/inspec/pull/2364) ([eramoto](https://github.com/eramoto)) <!-- 1.46.6 -->
22
- - json resource: ensure params is not nil in event of read/parse failure [#2354](https://github.com/chef/inspec/pull/2354) ([adamleff](https://github.com/adamleff)) <!-- 1.46.4 -->
23
- - Unique export file for security policy resource [#2350](https://github.com/chef/inspec/pull/2350) ([jquick](https://github.com/jquick)) <!-- 1.46.3 -->
24
- <!-- release_rollup -->
36
+ - Unique export file for security policy resource [#2350](https://github.com/chef/inspec/pull/2350) ([jquick](https://github.com/jquick))
37
+ - json resource: ensure params is not nil in event of read/parse failure [#2354](https://github.com/chef/inspec/pull/2354) ([adamleff](https://github.com/adamleff))
38
+ - key_rsa resource: fix inline shell documentation help, wrong resource name used in examples [#2364](https://github.com/chef/inspec/pull/2364) ([eramoto](https://github.com/eramoto))
39
+ - security_policy resource: use PID for filename instead of random [#2368](https://github.com/chef/inspec/pull/2368) ([jquick](https://github.com/jquick))
25
40
 
41
+ #### Merged Pull Requests
42
+ - docker_image resource: properly handle registries in image strings [#2356](https://github.com/chef/inspec/pull/2356) ([adamleff](https://github.com/adamleff))
26
43
  <!-- latest_stable_release -->
44
+
27
45
  ## [v1.46.2](https://github.com/chef/inspec/tree/v1.46.2) (2017-11-29)
28
46
 
29
47
  #### Enhancements
@@ -36,7 +54,6 @@
36
54
  - file resource: fix NilClass error when using advanced windows permissions [#2344](https://github.com/chef/inspec/pull/2344) ([TheLonelyGhost](https://github.com/TheLonelyGhost))
37
55
  - wmi resource: properly escape quotes in WMI query [#2342](https://github.com/chef/inspec/pull/2342) ([TheLonelyGhost](https://github.com/TheLonelyGhost))
38
56
  - Allow skipping/failing resources in FilterTable [#2349](https://github.com/chef/inspec/pull/2349) ([jerryaldrichiii](https://github.com/jerryaldrichiii))
39
- <!-- latest_stable_release -->
40
57
 
41
58
  ## [v1.45.13](https://github.com/chef/inspec/tree/v1.45.13) (2017-11-21)
42
59
 
data/Gemfile CHANGED
@@ -12,7 +12,7 @@ gem 'ffi', '>= 1.9.14'
12
12
  group :test do
13
13
  gem 'bundler', '~> 1.5'
14
14
  gem 'minitest', '~> 5.5'
15
- gem 'rake', '~> 10'
15
+ gem 'rake', '>= 10'
16
16
  gem 'rubocop', '= 0.49.1'
17
17
  gem 'simplecov', '~> 0.10'
18
18
  gem 'concurrent-ruby', '~> 0.9'
@@ -26,10 +26,9 @@ Gem::Specification.new do |spec|
26
26
 
27
27
  spec.required_ruby_version = '>= 2.3'
28
28
 
29
- spec.add_dependency 'train', '~> 0.30'
29
+ spec.add_dependency 'train', '~> 0.31', '>= 0.31.1'
30
30
  spec.add_dependency 'thor', '~> 0.19'
31
31
  spec.add_dependency 'json', '>= 1.8', '< 3.0'
32
- spec.add_dependency 'rainbow', '~> 2'
33
32
  spec.add_dependency 'method_source', '~> 0.8'
34
33
  spec.add_dependency 'rubyzip', '~> 1.1'
35
34
  spec.add_dependency 'rspec', '~> 3'
@@ -40,7 +40,7 @@ module Inspec
40
40
  #
41
41
  # @param [Hash] config for the transport backend
42
42
  # @return [TransportBackend] enriched transport instance
43
- def self.create(config)
43
+ def self.create(config) # rubocop:disable Metrics/AbcSize
44
44
  conf = Train.target_config(config)
45
45
  name = Train.validate_backend(conf)
46
46
  transport = Train.create(name, conf)
@@ -56,12 +56,15 @@ module Inspec
56
56
  # Set caching settings. We always want to enable caching for
57
57
  # the Mock transport for testing.
58
58
  if config[:backend_cache] || config[:backend] == :mock
59
+ Inspec::Log.debug 'Option backend_cache is enabled'
59
60
  connection.enable_cache(:file)
60
61
  connection.enable_cache(:command)
61
62
  elsif config[:debug_shell]
63
+ Inspec::Log.debug 'Option backend_cache is disabled'
62
64
  connection.disable_cache(:file)
63
65
  connection.disable_cache(:command)
64
66
  else
67
+ Inspec::Log.debug 'Option backend_cache is disabled'
65
68
  connection.disable_cache(:command)
66
69
  end
67
70
 
@@ -59,18 +59,28 @@ module Inspec
59
59
  desc: 'A list of controls to run. Ignore all other tests.'
60
60
  option :format, type: :string,
61
61
  desc: 'Which formatter to use: cli, progress, documentation, json, json-min, junit'
62
- option :color, type: :boolean, default: true,
62
+ option :color, type: :boolean,
63
63
  desc: 'Use colors in output.'
64
64
  option :attrs, type: :array,
65
65
  desc: 'Load attributes file (experimental)'
66
66
  option :cache, type: :string,
67
67
  desc: 'Use the given path for caching dependencies. (default: ~/.inspec/cache)'
68
- option :create_lockfile, type: :boolean, default: true,
68
+ option :create_lockfile, type: :boolean,
69
69
  desc: 'Write out a lockfile based on this execution (unless one already exists)'
70
- option :backend_cache, type: :boolean, default: false,
70
+ option :backend_cache, type: :boolean,
71
71
  desc: 'Allow caching for backend command output.'
72
72
  end
73
73
 
74
+ def self.default_options
75
+ {
76
+ exec: {
77
+ 'color' => true,
78
+ 'create_lockfile' => true,
79
+ 'backend_cache' => false,
80
+ },
81
+ }
82
+ end
83
+
74
84
  private
75
85
 
76
86
  # helper method to run tests
@@ -101,8 +111,8 @@ module Inspec
101
111
  puts
102
112
  end
103
113
 
104
- def opts
105
- o = merged_opts
114
+ def opts(type = nil)
115
+ o = merged_opts(type)
106
116
 
107
117
  # Due to limitations in Thor it is not possible to set an argument to be
108
118
  # both optional and its value to be mandatory. E.g. the user supplying
@@ -118,9 +128,18 @@ module Inspec
118
128
  o
119
129
  end
120
130
 
121
- def merged_opts
122
- # argv overrides json
123
- Thor::CoreExt::HashWithIndifferentAccess.new(options_json.merge(options))
131
+ def merged_opts(type = nil)
132
+ opts = {}
133
+
134
+ # start with default options if we have any
135
+ opts = BaseCLI.default_options[type] unless type.nil?
136
+
137
+ # merge in any options from json-config
138
+ opts.merge!(options_json)
139
+
140
+ # merge in any options defined via thor
141
+ opts.merge!(options)
142
+ Thor::CoreExt::HashWithIndifferentAccess.new(opts)
124
143
  end
125
144
 
126
145
  def options_json
@@ -62,6 +62,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
62
62
  o = opts.dup
63
63
  o[:ignore_supports] = true # we check for integrity only
64
64
  o[:backend] = Inspec::Backend.create(target: 'mock://')
65
+ o[:check_mode] = true
65
66
 
66
67
  # run check
67
68
  profile = Inspec::Profile.for_target(path, o)
@@ -151,8 +152,8 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
151
152
  exec_options
152
153
  def exec(*targets)
153
154
  diagnose
154
- configure_logger(opts)
155
- o = opts.dup
155
+ o = opts(:exec).dup
156
+ configure_logger(o)
156
157
 
157
158
  # run tests
158
159
  run_tests(targets, o)
@@ -13,7 +13,7 @@ module Inspec
13
13
  # as the basic DSL of the control files (describe, control, title,
14
14
  # etc).
15
15
  #
16
- class ControlEvalContext
16
+ class ControlEvalContext # rubocop:disable Metrics/ClassLength
17
17
  # Create the context for controls. This includes all components of the DSL,
18
18
  # including matchers and resources.
19
19
  #
@@ -47,12 +47,13 @@ module Inspec
47
47
 
48
48
  attr_accessor :skip_file
49
49
 
50
- def initialize(backend, conf, dependencies, require_loader)
50
+ def initialize(backend, conf, dependencies, require_loader, skip_only_if_eval)
51
51
  @backend = backend
52
52
  @conf = conf
53
53
  @dependencies = dependencies
54
54
  @require_loader = require_loader
55
55
  @skip_file = false
56
+ @skip_only_if_eval = skip_only_if_eval
56
57
  end
57
58
 
58
59
  define_method :title do |arg|
@@ -70,6 +71,7 @@ module Inspec
70
71
  define_method :control do |*args, &block|
71
72
  id = args[0]
72
73
  opts = args[1] || {}
74
+ opts[:skip_only_if_eval] = @skip_only_if_eval
73
75
  register_control(rule_class.new(id, profile_id, opts, &block))
74
76
  end
75
77
 
@@ -133,7 +135,10 @@ module Inspec
133
135
 
134
136
  define_method :only_if do |&block|
135
137
  return unless block
136
- return if @skip_file == true || block.yield == true
138
+ return if @skip_file == true
139
+ return if @skip_only_if_eval == true
140
+
141
+ return if block.yield == true
137
142
 
138
143
  # Apply `set_skip_rule` for other rules in the same file
139
144
  profile_context_owner.rules.values.each do |r|
@@ -78,7 +78,7 @@ module Inspec
78
78
  for_fetcher(fetcher, opts)
79
79
  end
80
80
 
81
- attr_reader :source_reader, :backend, :runner_context
81
+ attr_reader :source_reader, :backend, :runner_context, :check_mode
82
82
  def_delegator :@source_reader, :tests
83
83
  def_delegator :@source_reader, :libraries
84
84
  def_delegator :@source_reader, :metadata
@@ -96,6 +96,7 @@ module Inspec
96
96
  @attr_values = options[:attributes]
97
97
  @tests_collected = false
98
98
  @libraries_loaded = false
99
+ @check_mode = options[:check_mode] || false
99
100
  Metadata.finalize(@source_reader.metadata, @profile_id, options)
100
101
 
101
102
  # if a backend has already been created, clone it so each profile has its own unique backend object
@@ -14,7 +14,8 @@ module Inspec
14
14
  class ProfileContext # rubocop:disable Metrics/ClassLength
15
15
  def self.for_profile(profile, backend, attributes)
16
16
  new(profile.name, backend, { 'profile' => profile,
17
- 'attributes' => attributes })
17
+ 'attributes' => attributes,
18
+ 'check_mode' => profile.check_mode })
18
19
  end
19
20
 
20
21
  attr_reader :attributes, :profile_id, :resource_registry, :backend
@@ -27,6 +28,7 @@ module Inspec
27
28
  @profile_id = profile_id
28
29
  @backend = backend
29
30
  @conf = conf.dup
31
+ @skip_only_if_eval = @conf['check_mode']
30
32
  @rules = {}
31
33
  @control_subcontexts = []
32
34
  @lib_subcontexts = []
@@ -53,7 +55,7 @@ module Inspec
53
55
  def control_eval_context
54
56
  @control_eval_context ||= begin
55
57
  ctx = Inspec::ControlEvalContext.create(self, to_resources_dsl)
56
- ctx.new(@backend, @conf, dependencies, @require_loader)
58
+ ctx.new(@backend, @conf, dependencies, @require_loader, @skip_only_if_eval)
57
59
  end
58
60
  end
59
61
 
@@ -776,8 +776,8 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
776
776
  examples[0][:message].to_s
777
777
  else
778
778
  [
779
- !fails.empty? ? "#{fails.uniq.length} failed" : nil,
780
- !skips.empty? ? "#{skips.uniq.length} skipped" : nil,
779
+ !fails.empty? ? "#{fails.length} failed" : nil,
780
+ !skips.empty? ? "#{skips.length} skipped" : nil,
781
781
  ].compact.join(' ')
782
782
  end
783
783
 
@@ -29,7 +29,7 @@ module Inspec
29
29
  @resource_dsl
30
30
  end
31
31
 
32
- def initialize(id, profile_id, _opts, &block)
32
+ def initialize(id, profile_id, opts, &block)
33
33
  @impact = nil
34
34
  @title = nil
35
35
  @desc = nil
@@ -44,6 +44,7 @@ module Inspec
44
44
  @__checks = []
45
45
  @__skip_rule = nil
46
46
  @__merge_count = 0
47
+ @__skip_only_if_eval = opts[:skip_only_if_eval]
47
48
 
48
49
  # evaluate the given definition
49
50
  instance_eval(&block) if block_given?
@@ -104,6 +105,8 @@ module Inspec
104
105
  # @return [nil]
105
106
  def only_if
106
107
  return unless block_given?
108
+ return if @__skip_only_if_eval == true
109
+
107
110
  @__skip_rule ||= !yield
108
111
  end
109
112
 
@@ -4,5 +4,5 @@
4
4
  # author: Christoph Hartmann
5
5
 
6
6
  module Inspec
7
- VERSION = '1.47.0'
7
+ VERSION = '1.48.0'
8
8
  end
@@ -45,9 +45,9 @@ module Inspec::Resources
45
45
  result.exit_status.to_i
46
46
  end
47
47
 
48
- def exist?
48
+ def exist? # rubocop:disable Metrics/AbcSize
49
49
  # silent for mock resources
50
- return false if inspec.os.name.nil?
50
+ return false if inspec.os.name.nil? || inspec.os.name == 'mock'
51
51
 
52
52
  if inspec.os.linux?
53
53
  res = inspec.backend.run_command("bash -c 'type \"#{@command}\"'")
@@ -56,7 +56,7 @@ module Inspec::Resources
56
56
  elsif inspec.os.unix?
57
57
  res = inspec.backend.run_command("type \"#{@command}\"")
58
58
  else
59
- warn "`command(#{@command}).exist?` is not suported on your OS: #{inspec.os[:name]}"
59
+ warn "`command(#{@command}).exist?` is not supported on your OS: #{inspec.os[:name]}"
60
60
  return false
61
61
  end
62
62
  res.exit_status.to_i == 0
@@ -1,15 +1,14 @@
1
1
  # encoding: utf-8
2
- # author: Adam Leff
3
2
 
4
3
  require 'utils/parser'
5
4
  require 'utils/filter'
6
5
 
7
6
  module Inspec::Resources
8
- class Crontab < Inspec.resource(1)
7
+ class Crontab < Inspec.resource(1) # rubocop:disable Metrics/ClassLength
9
8
  name 'crontab'
10
9
  desc 'Use the crontab InSpec audit resource to test the contents of the crontab for a given user which contains information about scheduled tasks owned by that user.'
11
10
  example "
12
- describe crontab('root') do
11
+ describe crontab(user: 'root') do
13
12
  its('commands') { should include '/path/to/some/script' }
14
13
  end
15
14
 
@@ -25,51 +24,40 @@ module Inspec::Resources
25
24
  describe crontab.where { command =~ /a partial command string/ } do
26
25
  its('entries.length') { should cmp 1 }
27
26
  end
27
+
28
+ describe crontab(path: '/etc/cron.d/some_crontab') do
29
+ its('commands') { should include '/path/to/some/script' }
30
+ end
28
31
  "
29
32
 
30
33
  attr_reader :params
31
34
 
32
35
  include CommentParser
33
36
 
34
- def initialize(user = nil)
35
- @user = user
37
+ def initialize(opts = nil)
38
+ if opts.respond_to?(:fetch)
39
+ Hash[opts.map { |k, v| [k.to_sym, v] }]
40
+ @user = opts.fetch(:user, nil)
41
+ @path = opts.fetch(:path, nil)
42
+ raise Inspec::Exceptions::ResourceFailed, 'A user or path must be supplied.' if @user.nil? && @path.nil?
43
+ else
44
+ @user = opts
45
+ @path = nil
46
+ end
47
+ raise Inspec::Exceptions::ResourceSkipped, 'The `crontab` resource is not supported on your OS.' unless inspec.os.unix?
36
48
  @params = read_crontab
37
-
38
- return skip_resource 'The `crontab` resource is not supported on your OS.' unless inspec.os.unix?
39
49
  end
40
50
 
41
51
  def read_crontab
42
- inspec.command(crontab_cmd).stdout.lines.map { |l| parse_crontab_line(l) }.compact
52
+ ct = is_system_crontab? ? inspec.file(@path).content : inspec.command(crontab_cmd).stdout
53
+ ct.lines.map { |l| parse_crontab_line(l) }.compact
43
54
  end
44
55
 
45
56
  def parse_crontab_line(l)
46
57
  data, = parse_comment_line(l, comment_char: '#', standalone_comments: false)
47
58
  return nil if data.nil? || data.empty?
48
59
 
49
- case data
50
- when /@hourly .*/
51
- { 'minute' => '0', 'hour' => '*', 'day' => '*', 'month' => '*', 'weekday' => '*', 'command' => data.split(/\s+/, 2).at(1) }
52
- when /@(midnight|daily) .*/
53
- { 'minute' => '0', 'hour' => '0', 'day' => '*', 'month' => '*', 'weekday' => '*', 'command' => data.split(/\s+/, 2).at(1) }
54
- when /@weekly .*/
55
- { 'minute' => '0', 'hour' => '0', 'day' => '*', 'month' => '*', 'weekday' => '0', 'command' => data.split(/\s+/, 2).at(1) }
56
- when /@monthly ./
57
- { 'minute' => '0', 'hour' => '0', 'day' => '1', 'month' => '*', 'weekday' => '*', 'command' => data.split(/\s+/, 2).at(1) }
58
- when /@(annually|yearly) .*/
59
- { 'minute' => '0', 'hour' => '0', 'day' => '1', 'month' => '1', 'weekday' => '*', 'command' => data.split(/\s+/, 2).at(1) }
60
- when /@reboot .*/
61
- { 'minute' => '-1', 'hour' => '-1', 'day' => '-1', 'month' => '-1', 'weekday' => '-1', 'command' => data.split(/\s+/, 2).at(1) }
62
- else
63
- elements = data.split(/\s+/, 6)
64
- {
65
- 'minute' => elements.at(0),
66
- 'hour' => elements.at(1),
67
- 'day' => elements.at(2),
68
- 'month' => elements.at(3),
69
- 'weekday' => elements.at(4),
70
- 'command' => elements.at(5),
71
- }
72
- end
60
+ is_system_crontab? ? parse_system_crontab(data) : parse_user_crontab(data)
73
61
  end
74
62
 
75
63
  def crontab_cmd
@@ -84,19 +72,98 @@ module Inspec::Resources
84
72
  .add(:days, field: 'day')
85
73
  .add(:months, field: 'month')
86
74
  .add(:weekdays, field: 'weekday')
75
+ .add(:user, field: 'user')
87
76
  .add(:commands, field: 'command')
88
77
 
89
78
  # rebuild the crontab line from raw content
90
79
  filter.add(:content) { |t, _|
91
80
  t.entries.map do |e|
92
- [e.minute, e.hour, e.day, e.month, e.weekday, e.command].join(' ')
81
+ [e.minute, e.hour, e.day, e.month, e.weekday, e.user, e.command].compact.join(' ')
93
82
  end.join("\n")
94
83
  }
95
84
 
96
85
  filter.connect(self, :params)
97
86
 
98
87
  def to_s
99
- @user.nil? ? 'crontab for current user' : "crontab for user #{@user}"
88
+ if is_system_crontab?
89
+ "crontab for path #{@path}"
90
+ elsif is_user_crontab?
91
+ "crontab for user #{@user}"
92
+ else
93
+ 'crontab for current user'
94
+ end
95
+ end
96
+
97
+ private
98
+
99
+ def is_system_crontab?
100
+ !@path.nil?
101
+ end
102
+
103
+ def is_user_crontab?
104
+ !@user.nil?
105
+ end
106
+
107
+ def parse_system_crontab(data)
108
+ case data
109
+ when /@hourly .*/
110
+ elements = data.split(/\s+/, 3)
111
+ { 'minute' => '0', 'hour' => '*', 'day' => '*', 'month' => '*', 'weekday' => '*', 'user' => elements.at(1), 'command' => elements.at(2) }
112
+ when /@(midnight|daily) .*/
113
+ elements = data.split(/\s+/, 3)
114
+ { 'minute' => '0', 'hour' => '0', 'day' => '*', 'month' => '*', 'weekday' => '*', 'user' => elements.at(1), 'command' => elements.at(2) }
115
+ when /@weekly .*/
116
+ elements = data.split(/\s+/, 3)
117
+ { 'minute' => '0', 'hour' => '0', 'day' => '*', 'month' => '*', 'weekday' => '0', 'user' => elements.at(1), 'command' => elements.at(2) }
118
+ when /@monthly ./
119
+ elements = data.split(/\s+/, 3)
120
+ { 'minute' => '0', 'hour' => '0', 'day' => '1', 'month' => '*', 'weekday' => '*', 'user' => elements.at(1), 'command' => elements.at(2) }
121
+ when /@(annually|yearly) .*/
122
+ elements = data.split(/\s+/, 3)
123
+ { 'minute' => '0', 'hour' => '0', 'day' => '1', 'month' => '1', 'weekday' => '*', 'user' => elements.at(1), 'command' => elements.at(2) }
124
+ when /@reboot .*/
125
+ elements = data.split(/\s+/, 3)
126
+ { 'minute' => '-1', 'hour' => '-1', 'day' => '-1', 'month' => '-1', 'weekday' => '-1', 'user' => elements.at(1), 'command' => elements.at(2) }
127
+ else
128
+ elements = data.split(/\s+/, 7)
129
+ {
130
+ 'minute' => elements.at(0),
131
+ 'hour' => elements.at(1),
132
+ 'day' => elements.at(2),
133
+ 'month' => elements.at(3),
134
+ 'weekday' => elements.at(4),
135
+ 'user' => elements.at(5),
136
+ 'command' => elements.at(6),
137
+ }
138
+ end
139
+ end
140
+
141
+ def parse_user_crontab(data)
142
+ case data
143
+ when /@hourly .*/
144
+ { 'minute' => '0', 'hour' => '*', 'day' => '*', 'month' => '*', 'weekday' => '*', 'user' => @user, 'command' => data.split(/\s+/, 2).at(1) }
145
+ when /@(midnight|daily) .*/
146
+ { 'minute' => '0', 'hour' => '0', 'day' => '*', 'month' => '*', 'weekday' => '*', 'user' => @user, 'command' => data.split(/\s+/, 2).at(1) }
147
+ when /@weekly .*/
148
+ { 'minute' => '0', 'hour' => '0', 'day' => '*', 'month' => '*', 'weekday' => '0', 'user' => @user, 'command' => data.split(/\s+/, 2).at(1) }
149
+ when /@monthly ./
150
+ { 'minute' => '0', 'hour' => '0', 'day' => '1', 'month' => '*', 'weekday' => '*', 'user' => @user, 'command' => data.split(/\s+/, 2).at(1) }
151
+ when /@(annually|yearly) .*/
152
+ { 'minute' => '0', 'hour' => '0', 'day' => '1', 'month' => '1', 'weekday' => '*', 'user' => @user, 'command' => data.split(/\s+/, 2).at(1) }
153
+ when /@reboot .*/
154
+ { 'minute' => '-1', 'hour' => '-1', 'day' => '-1', 'month' => '-1', 'weekday' => '-1', 'user' => @user, 'command' => data.split(/\s+/, 2).at(1) }
155
+ else
156
+ elements = data.split(/\s+/, 6)
157
+ {
158
+ 'minute' => elements.at(0),
159
+ 'hour' => elements.at(1),
160
+ 'day' => elements.at(2),
161
+ 'month' => elements.at(3),
162
+ 'weekday' => elements.at(4),
163
+ 'user' => @user,
164
+ 'command' => elements.at(5),
165
+ }
166
+ end
100
167
  end
101
168
  end
102
169
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.47.0
4
+ version: 1.48.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dominik Richter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-04 00:00:00.000000000 Z
11
+ date: 2017-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: train
@@ -16,14 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.30'
19
+ version: '0.31'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.31.1
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - "~>"
25
28
  - !ruby/object:Gem::Version
26
- version: '0.30'
29
+ version: '0.31'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.31.1
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: thor
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -58,20 +64,6 @@ dependencies:
58
64
  - - "<"
59
65
  - !ruby/object:Gem::Version
60
66
  version: '3.0'
61
- - !ruby/object:Gem::Dependency
62
- name: rainbow
63
- requirement: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - "~>"
66
- - !ruby/object:Gem::Version
67
- version: '2'
68
- type: :runtime
69
- prerelease: false
70
- version_requirements: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - "~>"
73
- - !ruby/object:Gem::Version
74
- version: '2'
75
67
  - !ruby/object:Gem::Dependency
76
68
  name: method_source
77
69
  requirement: !ruby/object:Gem::Requirement