inspec-core 4.17.17 → 4.18.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 +4 -4
- data/lib/inspec/base_cli.rb +5 -1
- data/lib/inspec/cli.rb +10 -1
- data/lib/inspec/dsl.rb +2 -0
- data/lib/inspec/formatters/base.rb +5 -0
- data/lib/inspec/reporters/json.rb +1 -1
- data/lib/inspec/resources/apt.rb +2 -0
- data/lib/inspec/resources/interface.rb +17 -19
- data/lib/inspec/resources/users.rb +73 -0
- data/lib/inspec/rspec_extensions.rb +1 -0
- data/lib/inspec/rule.rb +4 -4
- data/lib/inspec/runner_rspec.rb +1 -1
- data/lib/inspec/schema.rb +10 -0
- data/lib/inspec/utils/parser.rb +8 -7
- data/lib/inspec/version.rb +1 -1
- data/lib/plugins/shared/core_plugin_test_helper.rb +16 -16
- metadata +10 -5
- data/lib/inspec/polyfill.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 965a170fc5beed002ad3a6ee98635fc4e6f5ffea8c546b35a6f16585f3c9c988
|
4
|
+
data.tar.gz: 73751911bb9d7b894df68b733dac98409bce75818d96401139094b9f8bfa7750
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 13481358fd713598dda518674674e4a74b819dbfcd096be411421d8b2170c0bc34bab6dc52057b757a5edacbada2cbe881a0363052e945ce2a9d76d3e8322b83
|
7
|
+
data.tar.gz: daad1335c0bfafffcf7b47f2f14293a8d636c34b9a8537570c68a5236d6ff0caf615e279d30d78d32edcf9a361934bfae22fe7081b1cfbd80705c3e807b0ac39
|
data/lib/inspec/base_cli.rb
CHANGED
@@ -222,16 +222,20 @@ module Inspec
|
|
222
222
|
|
223
223
|
private
|
224
224
|
|
225
|
+
ALL_OF_OUR_REPORTERS = %w{json json-min json-rspec json-automate junit html yaml documentation progress}.freeze # BUT WHY?!?!
|
226
|
+
|
225
227
|
def suppress_log_output?(opts)
|
226
228
|
return false if opts["reporter"].nil?
|
227
229
|
|
228
|
-
match =
|
230
|
+
match = ALL_OF_OUR_REPORTERS & opts["reporter"].keys
|
231
|
+
|
229
232
|
unless match.empty?
|
230
233
|
match.each do |m|
|
231
234
|
# check to see if we are outputting to stdout
|
232
235
|
return true if opts["reporter"][m]["stdout"] == true
|
233
236
|
end
|
234
237
|
end
|
238
|
+
|
235
239
|
false
|
236
240
|
end
|
237
241
|
|
data/lib/inspec/cli.rb
CHANGED
@@ -9,6 +9,7 @@ module Inspec # TODO: move this somewhere "better"?
|
|
9
9
|
autoload :BaseCLI, "inspec/base_cli"
|
10
10
|
autoload :Deprecation, "inspec/utils/deprecation"
|
11
11
|
autoload :Exceptions, "inspec/exceptions"
|
12
|
+
autoload :EnvPrinter, "inspec/env_printer"
|
12
13
|
autoload :Fetcher, "inspec/fetcher"
|
13
14
|
autoload :Formatters, "inspec/formatters"
|
14
15
|
autoload :Globals, "inspec/globals"
|
@@ -340,7 +341,15 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
340
341
|
ui.exit res unless run_type == :ruby_eval
|
341
342
|
|
342
343
|
# No InSpec tests - just print evaluation output.
|
343
|
-
|
344
|
+
reporters = o["reporter"] || {}
|
345
|
+
if reporters.keys.include?("json")
|
346
|
+
res = if res.respond_to?(:to_json)
|
347
|
+
res.to_json
|
348
|
+
else
|
349
|
+
JSON.dump(res)
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
344
353
|
puts res
|
345
354
|
ui.exit Inspec::UI::EXIT_NORMAL
|
346
355
|
rescue RuntimeError, Train::UserError => e
|
data/lib/inspec/dsl.rb
CHANGED
@@ -259,6 +259,11 @@ module Inspec::Formatters
|
|
259
259
|
example.delete(:id)
|
260
260
|
example.delete(:profile_id)
|
261
261
|
control[:results].push(example)
|
262
|
+
|
263
|
+
# Waiver data, if available, is internally stored on a per-result
|
264
|
+
# (that is, per-describe-block) basis, because that is the only granularity
|
265
|
+
# available to us in the RSpec report data structure which we use as a vehicle.
|
266
|
+
control[:waiver_data] ||= example[:waiver_data] || {}
|
262
267
|
end
|
263
268
|
end
|
264
269
|
end
|
@@ -40,7 +40,6 @@ module Inspec::Reporters
|
|
40
40
|
message: r[:message],
|
41
41
|
exception: r[:exception],
|
42
42
|
backtrace: r[:backtrace],
|
43
|
-
waiver_data: r[:waiver_data],
|
44
43
|
}.reject { |_k, v| v.nil? }
|
45
44
|
}
|
46
45
|
end
|
@@ -96,6 +95,7 @@ module Inspec::Reporters
|
|
96
95
|
line: c[:source_location][:line],
|
97
96
|
ref: c[:source_location][:ref],
|
98
97
|
},
|
98
|
+
waiver_data: c[:waiver_data] || {},
|
99
99
|
results: profile_results(c),
|
100
100
|
}
|
101
101
|
}
|
data/lib/inspec/resources/apt.rb
CHANGED
@@ -87,12 +87,14 @@ module Inspec::Resources
|
|
87
87
|
active = raw_line == line
|
88
88
|
|
89
89
|
# formats:
|
90
|
+
# deb "http://archive.ubuntu.com/ubuntu/" wily main restricted ...
|
90
91
|
# deb http://archive.ubuntu.com/ubuntu/ wily main restricted ...
|
91
92
|
# deb [trusted=yes] http://archive.ubuntu.com/ubuntu/ wily main restricted ...
|
92
93
|
|
93
94
|
words = line.split
|
94
95
|
words.delete 1 if words[1] && words[1].start_with?("[")
|
95
96
|
type, url, distro, *components = words
|
97
|
+
url = url.delete('"') if url
|
96
98
|
|
97
99
|
next if components.empty?
|
98
100
|
next unless URI::HTTP === URI.parse(url)
|
@@ -17,38 +17,34 @@ module Inspec::Resources
|
|
17
17
|
its('ipv6_cidrs') { should include '::1/128' }
|
18
18
|
end
|
19
19
|
EXAMPLE
|
20
|
+
|
20
21
|
def initialize(iface)
|
21
22
|
@iface = iface
|
22
|
-
|
23
|
-
@interface_provider = nil
|
24
|
-
if inspec.os.linux?
|
25
|
-
@interface_provider = LinuxInterface.new(inspec)
|
26
|
-
elsif inspec.os.windows?
|
27
|
-
@interface_provider = WindowsInterface.new(inspec)
|
28
|
-
else
|
29
|
-
return skip_resource "The `interface` resource is not supported on your OS yet."
|
30
|
-
end
|
31
23
|
end
|
32
24
|
|
33
25
|
def exists?
|
34
|
-
|
26
|
+
!!(interface_info && interface_info[:name])
|
35
27
|
end
|
36
28
|
|
37
29
|
def up?
|
38
|
-
interface_info
|
30
|
+
!!(interface_info && interface_info[:up])
|
31
|
+
end
|
32
|
+
|
33
|
+
def name
|
34
|
+
interface_info[:name]
|
39
35
|
end
|
40
36
|
|
41
37
|
# returns link speed in Mbits/sec
|
42
38
|
def speed
|
43
|
-
interface_info
|
39
|
+
interface_info && interface_info[:speed]
|
44
40
|
end
|
45
41
|
|
46
42
|
def ipv4_address?
|
47
|
-
|
43
|
+
ipv4_addresses && !ipv4_addresses.empty?
|
48
44
|
end
|
49
45
|
|
50
46
|
def ipv6_address?
|
51
|
-
|
47
|
+
ipv6_addresses && !ipv6_addresses.empty?
|
52
48
|
end
|
53
49
|
|
54
50
|
def ipv4_addresses
|
@@ -72,11 +68,11 @@ module Inspec::Resources
|
|
72
68
|
end
|
73
69
|
|
74
70
|
def ipv4_cidrs
|
75
|
-
interface_info
|
71
|
+
interface_info && Array(interface_info[:ipv4_addresses])
|
76
72
|
end
|
77
73
|
|
78
74
|
def ipv6_cidrs
|
79
|
-
interface_info
|
75
|
+
interface_info && Array(interface_info[:ipv6_addresses])
|
80
76
|
end
|
81
77
|
|
82
78
|
def to_s
|
@@ -86,9 +82,11 @@ module Inspec::Resources
|
|
86
82
|
private
|
87
83
|
|
88
84
|
def interface_info
|
89
|
-
|
90
|
-
|
91
|
-
|
85
|
+
@cache ||= begin
|
86
|
+
provider = LinuxInterface.new(inspec) if inspec.os.linux?
|
87
|
+
provider = WindowsInterface.new(inspec) if inspec.os.windows?
|
88
|
+
Hash(provider && provider.interface_info(@iface))
|
89
|
+
end
|
92
90
|
end
|
93
91
|
end
|
94
92
|
|
@@ -3,6 +3,7 @@ require "inspec/utils/convert"
|
|
3
3
|
require "inspec/utils/filter"
|
4
4
|
require "inspec/utils/simpleconfig"
|
5
5
|
require "inspec/resources/powershell"
|
6
|
+
require "date"
|
6
7
|
|
7
8
|
module Inspec::Resources
|
8
9
|
# This file contains two resources, the `user` and `users` resource.
|
@@ -116,6 +117,24 @@ module Inspec::Resources
|
|
116
117
|
# its('mindays') { should eq 0 }
|
117
118
|
# its('maxdays') { should eq 99 }
|
118
119
|
# its('warndays') { should eq 5 }
|
120
|
+
# its('passwordage') { should be >= 0 }
|
121
|
+
# its('maxbadpasswords') { should eq nil } // not yet supported on linux
|
122
|
+
# its('badpasswordattempts') { should eq 0 }
|
123
|
+
# end
|
124
|
+
# describe user('Administrator') do
|
125
|
+
# it { should exist }
|
126
|
+
# its('uid') { should eq "S-1-5-21-1759981009-4135989804-1844563890-500" }
|
127
|
+
# its('gid') { should eq nil } // not supported on Windows
|
128
|
+
# its('group') { should eq nil } // not supported on Windows
|
129
|
+
# its('groups') { should eq ['Administrators', 'Users']}
|
130
|
+
# its('home') { should eq '' }
|
131
|
+
# its('shell') { should eq nil } // not supported on Windows
|
132
|
+
# its('mindays') { should eq 0 }
|
133
|
+
# its('maxdays') { should eq 42 }
|
134
|
+
# its('warndays') { should eq nil }
|
135
|
+
# its('passwordage') { should eq 355 }
|
136
|
+
# its('maxbadpasswords') { should eq 0 }
|
137
|
+
# its('badpasswordattempts') { should eq 0 }
|
119
138
|
# end
|
120
139
|
#
|
121
140
|
# The following Serverspec matchers are deprecated in favor for direct value access
|
@@ -196,6 +215,14 @@ module Inspec::Resources
|
|
196
215
|
meta_info[:shell] unless meta_info.nil?
|
197
216
|
end
|
198
217
|
|
218
|
+
def domain
|
219
|
+
meta_info[:domain] unless meta_info.nil?
|
220
|
+
end
|
221
|
+
|
222
|
+
def userflags
|
223
|
+
meta_info[:userflags] unless meta_info.nil?
|
224
|
+
end
|
225
|
+
|
199
226
|
# returns the minimum days between password changes
|
200
227
|
def mindays
|
201
228
|
credentials[:mindays] unless credentials.nil?
|
@@ -211,6 +238,18 @@ module Inspec::Resources
|
|
211
238
|
credentials[:warndays] unless credentials.nil?
|
212
239
|
end
|
213
240
|
|
241
|
+
def badpasswordattempts
|
242
|
+
credentials[:badpasswordattempts] unless credentials.nil?
|
243
|
+
end
|
244
|
+
|
245
|
+
def maxbadpasswords
|
246
|
+
credentials[:maxbadpasswords] unless credentials.nil?
|
247
|
+
end
|
248
|
+
|
249
|
+
def passwordage
|
250
|
+
credentials[:passwordage] unless credentials.nil?
|
251
|
+
end
|
252
|
+
|
214
253
|
# implement 'mindays' method to be compatible with serverspec
|
215
254
|
def minimum_days_between_password_change
|
216
255
|
Inspec.deprecate(:resource_user_serverspec_compat, "The user resource `minimum_days_between_password_change` property is deprecated. Please use `mindays`.")
|
@@ -425,10 +464,17 @@ module Inspec::Resources
|
|
425
464
|
multiple_values: false
|
426
465
|
).params
|
427
466
|
|
467
|
+
dparse = Date.parse "#{params['Last password change']}"
|
468
|
+
dayslastset = (Date.today - dparse).to_i
|
469
|
+
cmd = inspec.command("lastb -w -a | grep #{username} | wc -l")
|
470
|
+
badpasswordattempts = convert_to_i(cmd.stdout.chomp) if cmd.exit_status == 0
|
471
|
+
|
428
472
|
{
|
429
473
|
mindays: convert_to_i(params["Minimum number of days between password change"]),
|
430
474
|
maxdays: convert_to_i(params["Maximum number of days between password change"]),
|
431
475
|
warndays: convert_to_i(params["Number of days of warning before password expires"]),
|
476
|
+
passwordage: dayslastset,
|
477
|
+
badpasswordattempts: badpasswordattempts,
|
432
478
|
}
|
433
479
|
end
|
434
480
|
end
|
@@ -481,6 +527,8 @@ module Inspec::Resources
|
|
481
527
|
mindays: user_sec[1].to_i * 7,
|
482
528
|
maxdays: user_sec[2].to_i * 7,
|
483
529
|
warndays: user_sec[3].to_i,
|
530
|
+
passwordage: nil,
|
531
|
+
badpasswordattempts: nil,
|
484
532
|
}
|
485
533
|
end
|
486
534
|
end
|
@@ -573,6 +621,31 @@ module Inspec::Resources
|
|
573
621
|
res[0] unless res.empty?
|
574
622
|
end
|
575
623
|
|
624
|
+
def meta_info(username)
|
625
|
+
res = identity(username)
|
626
|
+
return if res.nil?
|
627
|
+
{
|
628
|
+
home: res[:home],
|
629
|
+
shell: res[:shell],
|
630
|
+
domain: res[:domain],
|
631
|
+
userflags: res[:userflags],
|
632
|
+
}
|
633
|
+
end
|
634
|
+
|
635
|
+
def credentials(username)
|
636
|
+
res = identity(username)
|
637
|
+
return if res.nil?
|
638
|
+
{
|
639
|
+
mindays: res[:mindays],
|
640
|
+
maxdays: res[:maxdays],
|
641
|
+
warndays: res[:warndays],
|
642
|
+
badpasswordattempts: res[:badpasswordattempts],
|
643
|
+
maxbadpasswords: res[:maxbadpasswords],
|
644
|
+
minpasswordlength: res[:minpasswordlength],
|
645
|
+
passwordage: res[:passwordage],
|
646
|
+
}
|
647
|
+
end
|
648
|
+
|
576
649
|
def list_users
|
577
650
|
collect_user_details.map { |user| user[:username] }
|
578
651
|
end
|
@@ -50,6 +50,7 @@ module Inspec
|
|
50
50
|
def method_missing(method_name, *arguments, &block)
|
51
51
|
# see if it is a resource first
|
52
52
|
begin
|
53
|
+
inspec = inspec if respond_to?(:inspec) # backend not available??
|
53
54
|
resource = Inspec::DSL.method_missing_resource(inspec, method_name, *arguments)
|
54
55
|
return resource if resource
|
55
56
|
rescue LoadError
|
data/lib/inspec/rule.rb
CHANGED
@@ -297,11 +297,11 @@ module Inspec
|
|
297
297
|
__waiver_data["skipped_due_to_waiver"] = false
|
298
298
|
__waiver_data["message"] = ""
|
299
299
|
|
300
|
-
# Waivers should have a hash value with keys possibly including
|
301
|
-
# expiration_date. We only care here if it has a
|
302
|
-
# is
|
300
|
+
# Waivers should have a hash value with keys possibly including "run" and
|
301
|
+
# expiration_date. We only care here if it has a "run" key and it
|
302
|
+
# is false-like, since all non-skipped waiver operations are handled
|
303
303
|
# during reporting phase.
|
304
|
-
return unless __waiver_data.key?("
|
304
|
+
return unless __waiver_data.key?("run") && !__waiver_data["run"]
|
305
305
|
|
306
306
|
# OK, the intent is to skip. Does it have an expiration date, and
|
307
307
|
# if so, is it in the future?
|
data/lib/inspec/runner_rspec.rb
CHANGED
@@ -83,7 +83,7 @@ module Inspec
|
|
83
83
|
return @rspec_exit_code if @formatter.results.empty?
|
84
84
|
|
85
85
|
stats = @formatter.results[:statistics][:controls]
|
86
|
-
skipped = @formatter.results
|
86
|
+
skipped = @formatter.results.dig(:profiles, 0, :status) == "skipped"
|
87
87
|
if stats[:failed][:total] == 0 && stats[:skipped][:total] == 0 && !skipped
|
88
88
|
0
|
89
89
|
elsif stats[:failed][:total] > 0
|
data/lib/inspec/schema.rb
CHANGED
@@ -96,6 +96,16 @@ module Inspec
|
|
96
96
|
},
|
97
97
|
},
|
98
98
|
"results" => { "type" => "array", "items" => RESULT },
|
99
|
+
"waiver_data" => {
|
100
|
+
"type" => "object",
|
101
|
+
"properties" => {
|
102
|
+
"skipped_due_to_waiver" => { "type" => "string" },
|
103
|
+
"run" => { "type" => "boolean" },
|
104
|
+
"message" => { "type" => "string" },
|
105
|
+
"expiration_date" => { "type" => "string" },
|
106
|
+
"justification" => { "type" => "string" },
|
107
|
+
},
|
108
|
+
},
|
99
109
|
},
|
100
110
|
}.freeze
|
101
111
|
|
data/lib/inspec/utils/parser.rb
CHANGED
@@ -20,13 +20,14 @@ module PasswdParser
|
|
20
20
|
def parse_passwd_line(line)
|
21
21
|
x = line.split(":")
|
22
22
|
{
|
23
|
-
|
24
|
-
"
|
25
|
-
"
|
26
|
-
"
|
27
|
-
"
|
28
|
-
"
|
29
|
-
"
|
23
|
+
# rubocop:disable Layout/AlignHash
|
24
|
+
"user" => x[0],
|
25
|
+
"password" => x[1],
|
26
|
+
"uid" => x[2],
|
27
|
+
"gid" => x[3],
|
28
|
+
"desc" => x[4],
|
29
|
+
"home" => x[5],
|
30
|
+
"shell" => x[6],
|
30
31
|
}
|
31
32
|
end
|
32
33
|
end
|
data/lib/inspec/version.rb
CHANGED
@@ -19,22 +19,22 @@ class Module
|
|
19
19
|
include Minitest::Spec::DSL # TODO: NO! remove this!
|
20
20
|
end
|
21
21
|
|
22
|
-
module Inspec
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
end
|
22
|
+
# module Inspec
|
23
|
+
# class FuncTestRunResult
|
24
|
+
# attr_reader :train_result
|
25
|
+
# attr_reader :payload
|
26
|
+
#
|
27
|
+
# extend Forwardable
|
28
|
+
# def_delegator :train_result, :stdout
|
29
|
+
# def_delegator :train_result, :stderr
|
30
|
+
# def_delegator :train_result, :exit_status
|
31
|
+
#
|
32
|
+
# def initialize(train_result)
|
33
|
+
# @train_result = train_result
|
34
|
+
# @payload = OpenStruct.new
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
# end
|
38
38
|
|
39
39
|
module CorePluginBaseHelper
|
40
40
|
libdir = File.expand_path "lib"
|
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.
|
4
|
+
version: 4.18.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: 2019-10-
|
11
|
+
date: 2019-10-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: train-core
|
@@ -106,14 +106,20 @@ dependencies:
|
|
106
106
|
requirements:
|
107
107
|
- - "~>"
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
version: '3'
|
109
|
+
version: '3.0'
|
110
|
+
- - "<"
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '3.9'
|
110
113
|
type: :runtime
|
111
114
|
prerelease: false
|
112
115
|
version_requirements: !ruby/object:Gem::Requirement
|
113
116
|
requirements:
|
114
117
|
- - "~>"
|
115
118
|
- !ruby/object:Gem::Version
|
116
|
-
version: '3'
|
119
|
+
version: '3.0'
|
120
|
+
- - "<"
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '3.9'
|
117
123
|
- !ruby/object:Gem::Dependency
|
118
124
|
name: rspec-its
|
119
125
|
requirement: !ruby/object:Gem::Requirement
|
@@ -449,7 +455,6 @@ files:
|
|
449
455
|
- lib/inspec/plugin/v2/plugin_types/mock.rb
|
450
456
|
- lib/inspec/plugin/v2/registry.rb
|
451
457
|
- lib/inspec/plugin/v2/status.rb
|
452
|
-
- lib/inspec/polyfill.rb
|
453
458
|
- lib/inspec/profile.rb
|
454
459
|
- lib/inspec/profile_context.rb
|
455
460
|
- lib/inspec/profile_vendor.rb
|