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 +4 -4
- data/CHANGELOG.md +32 -15
- data/Gemfile +1 -1
- data/inspec.gemspec +1 -2
- data/lib/inspec/backend.rb +4 -1
- data/lib/inspec/base_cli.rb +27 -8
- data/lib/inspec/cli.rb +3 -2
- data/lib/inspec/control_eval_context.rb +8 -3
- data/lib/inspec/profile.rb +2 -1
- data/lib/inspec/profile_context.rb +4 -2
- data/lib/inspec/rspec_json_formatter.rb +2 -2
- data/lib/inspec/rule.rb +4 -1
- data/lib/inspec/version.rb +1 -1
- data/lib/resources/command.rb +3 -3
- data/lib/resources/crontab.rb +101 -34
- metadata +10 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '012308b85533b4379b4dae9b2d6bb956e4716dea'
|
4
|
+
data.tar.gz: a621d9a79814290988494ec07da9bad51057f33b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 93b4c27033acdb1e4559c48940d0c73b1d94b3b20e109ed6a3b2ecf57908143b8c133717790ff273253aa580d893ee3ecd9a75e1129d9125bbc64f2c7c2d8397
|
7
|
+
data.tar.gz: 8eb7fe1e83c0bba17b5ef763015c83be4952c622e80a80af68a702d829d78bed389864157cdee86352f4ae166213ddc17b4fd5fbd5455719c89c8efc3de77a30
|
data/CHANGELOG.md
CHANGED
@@ -1,29 +1,47 @@
|
|
1
1
|
# Change Log
|
2
2
|
<!-- usage documentation: http://expeditor-docs.es.chef.io/configuration/changelog/ -->
|
3
|
-
<!-- latest_release 1.
|
4
|
-
## [v1.
|
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
|
-
####
|
7
|
-
-
|
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.
|
11
|
-
### Changes since 1.
|
10
|
+
<!-- release_rollup since=1.47.0 -->
|
11
|
+
### Changes since 1.47.0 release
|
12
12
|
|
13
|
-
####
|
14
|
-
-
|
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
|
-
-
|
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
|
-
-
|
21
|
-
-
|
22
|
-
-
|
23
|
-
-
|
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
data/inspec.gemspec
CHANGED
@@ -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.
|
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'
|
data/lib/inspec/backend.rb
CHANGED
@@ -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
|
|
data/lib/inspec/base_cli.rb
CHANGED
@@ -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,
|
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,
|
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,
|
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
|
-
|
123
|
-
|
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
|
data/lib/inspec/cli.rb
CHANGED
@@ -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
|
-
|
155
|
-
o
|
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
|
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|
|
data/lib/inspec/profile.rb
CHANGED
@@ -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.
|
780
|
-
!skips.empty? ? "#{skips.
|
779
|
+
!fails.empty? ? "#{fails.length} failed" : nil,
|
780
|
+
!skips.empty? ? "#{skips.length} skipped" : nil,
|
781
781
|
].compact.join(' ')
|
782
782
|
end
|
783
783
|
|
data/lib/inspec/rule.rb
CHANGED
@@ -29,7 +29,7 @@ module Inspec
|
|
29
29
|
@resource_dsl
|
30
30
|
end
|
31
31
|
|
32
|
-
def initialize(id, profile_id,
|
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
|
|
data/lib/inspec/version.rb
CHANGED
data/lib/resources/command.rb
CHANGED
@@ -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
|
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
|
data/lib/resources/crontab.rb
CHANGED
@@ -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(
|
35
|
-
|
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.
|
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
|
-
|
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
|
-
|
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.
|
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-
|
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.
|
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.
|
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
|