inspec-core 4.18.85 → 4.18.97
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/Gemfile +3 -2
- data/README.md +2 -2
- data/inspec-core.gemspec +1 -1
- data/lib/inspec/cli.rb +4 -4
- data/lib/inspec/globals.rb +7 -1
- data/lib/inspec/library_eval_context.rb +34 -36
- data/lib/inspec/plugin/v2/loader.rb +13 -5
- data/lib/inspec/resources/auditd.rb +13 -1
- data/lib/inspec/resources/oracledb_session.rb +6 -56
- data/lib/inspec/schema/README.md +17 -0
- data/lib/inspec/schema/exec_json.rb +128 -0
- data/lib/inspec/schema/exec_json_min.rb +40 -0
- data/lib/inspec/schema/output_schema.rb +53 -0
- data/lib/inspec/schema/primitives.rb +266 -0
- data/lib/inspec/schema/profile_json.rb +60 -0
- data/lib/inspec/utils/install_context.rb +60 -0
- data/lib/inspec/version.rb +1 -1
- metadata +12 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6b39b8f2921accd19eb170e079a3b85bfb72611d618d5bc0b0c705eb08000323
|
4
|
+
data.tar.gz: 2c6a90407e96b9038044f03884bc0b2c842f06ef410139f929d6149717a49ea4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: da18afb78ba9601984a36e2f8557cde0c0c316083e99e6f3b86162c8130970cba53f0b04c896bb3b87d29ad6fe76a85fea46339ee4799d4c827eda587b880a35
|
7
|
+
data.tar.gz: 71473c95ca6a3b4c36e71edab3663157aa4590ac41dcf26148d6baad03655287ae689ae525fcaa0b56e55d5041b69a0deeeb7207ee7454554e205c30c7476dfe
|
data/Gemfile
CHANGED
@@ -23,7 +23,7 @@ group :test do
|
|
23
23
|
gem "minitest", "~> 5.5"
|
24
24
|
gem "minitest-sprint", "~> 1.0"
|
25
25
|
gem "rake", ">= 10"
|
26
|
-
gem "simplecov", "~> 0.10"
|
26
|
+
gem "simplecov", ["~> 0.10", "<=0.18.2"]
|
27
27
|
gem "concurrent-ruby", "~> 1.0"
|
28
28
|
gem "mocha", "~> 1.1"
|
29
29
|
gem "ruby-progressbar", "~> 1.8"
|
@@ -35,9 +35,10 @@ end
|
|
35
35
|
|
36
36
|
group :integration do
|
37
37
|
gem "berkshelf"
|
38
|
-
gem "chef", "< 15"
|
39
38
|
gem "test-kitchen"
|
40
39
|
gem "kitchen-vagrant"
|
40
|
+
gem "chef", "< 15"
|
41
|
+
gem "chef-zero", "< 15"
|
41
42
|
gem "kitchen-inspec"
|
42
43
|
gem "kitchen-ec2"
|
43
44
|
gem "kitchen-dokken"
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Chef InSpec: Inspect Your Infrastructure
|
2
2
|
|
3
3
|
* **Project State: Active**
|
4
|
-
* **Issues Response SLA:
|
5
|
-
* **Pull Request Response SLA:
|
4
|
+
* **Issues Response SLA: 14 business days**
|
5
|
+
* **Pull Request Response SLA: 14 business days**
|
6
6
|
|
7
7
|
For more information on project states and SLAs, see [this documentation](https://github.com/chef/chef-oss-practices/blob/master/repo-management/repo-states.md).
|
8
8
|
|
data/inspec-core.gemspec
CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_dependency "chef-telemetry", "~> 1.0"
|
27
27
|
spec.add_dependency "license-acceptance", ">= 0.2.13", "< 2.0"
|
28
28
|
spec.add_dependency "thor", ">= 0.20", "< 2.0"
|
29
|
-
spec.add_dependency "
|
29
|
+
spec.add_dependency "json_schemer", "~> 0.2.1"
|
30
30
|
spec.add_dependency "method_source", "~> 0.8"
|
31
31
|
spec.add_dependency "rubyzip", "~> 1.2", ">= 1.2.2"
|
32
32
|
spec.add_dependency "rspec", "~> 3.9"
|
data/lib/inspec/cli.rb
CHANGED
@@ -377,12 +377,12 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
377
377
|
|
378
378
|
desc "schema NAME", "print the JSON schema", hide: true
|
379
379
|
def schema(name)
|
380
|
-
require "inspec/schema"
|
380
|
+
require "inspec/schema/output_schema"
|
381
381
|
|
382
|
-
puts Inspec::Schema.json(name)
|
382
|
+
puts Inspec::Schema::OutputSchema.json(name)
|
383
383
|
rescue StandardError => e
|
384
384
|
puts e
|
385
|
-
puts "Valid schemas are #{Inspec::Schema.names.join(", ")}"
|
385
|
+
puts "Valid schemas are #{Inspec::Schema::OutputSchema.names.join(", ")}"
|
386
386
|
end
|
387
387
|
|
388
388
|
desc "version", "prints the version of this tool"
|
@@ -470,5 +470,5 @@ rescue Inspec::Plugin::V2::Exception => v2ex
|
|
470
470
|
else
|
471
471
|
Inspec::Log.error "Run again with --debug for a stacktrace."
|
472
472
|
end
|
473
|
-
|
473
|
+
exit Inspec::UI::EXIT_PLUGIN_ERROR
|
474
474
|
end
|
data/lib/inspec/globals.rb
CHANGED
@@ -1,9 +1,15 @@
|
|
1
|
+
require_relative "utils/install_context"
|
2
|
+
|
1
3
|
module Inspec
|
4
|
+
|
5
|
+
extend Inspec::InstallContextHelpers
|
6
|
+
|
2
7
|
def self.config_dir
|
3
8
|
ENV["INSPEC_CONFIG_DIR"] ? ENV["INSPEC_CONFIG_DIR"] : File.join(Dir.home, ".inspec")
|
4
9
|
end
|
5
10
|
|
6
11
|
def self.src_root
|
7
|
-
File.expand_path(File.join(__FILE__, "
|
12
|
+
@src_root ||= File.expand_path(File.join(__FILE__, "../../.."))
|
8
13
|
end
|
14
|
+
|
9
15
|
end
|
@@ -12,44 +12,42 @@ module Inspec
|
|
12
12
|
# registry used by all dsl methods bound to the resource registry
|
13
13
|
# passed into the #create constructor.
|
14
14
|
#
|
15
|
+
#
|
15
16
|
class LibraryEvalContext
|
16
|
-
# rubocop:disable Naming/ConstantName
|
17
|
-
Inspec = :nope! # see #initialize below
|
18
|
-
# rubocop:enable Naming/ConstantName
|
19
|
-
|
20
|
-
##
|
21
|
-
# Include a custom `require` method that gets used when this
|
22
|
-
# context is used to eval source. See lib/inspec/dsl_shared.rb for
|
23
|
-
# more details.
|
24
|
-
include ::Inspec::DSL::RequireOverride
|
25
|
-
|
26
17
|
def self.create(registry, require_loader)
|
27
|
-
Class.new(
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
18
|
+
c = Class.new(Inspec::Resource) do
|
19
|
+
define_singleton_method :__resource_registry do
|
20
|
+
registry
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
c2 = Class.new do
|
25
|
+
define_singleton_method :resource do |version|
|
26
|
+
Inspec.validate_resource_dsl_version!(version)
|
27
|
+
c
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
c3 = Class.new do
|
32
|
+
include Inspec::DSL::RequireOverride
|
33
|
+
def initialize(require_loader)
|
34
|
+
@require_loader = require_loader
|
35
|
+
@inspec_binding = nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def __inspec_binding
|
39
|
+
@inspec_binding
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
c3.const_set(:Inspec, c2)
|
44
|
+
res = c3.new(require_loader)
|
45
|
+
|
46
|
+
# Provide the local binding for this context which is necessary for
|
47
|
+
# calls to `require` to create all dependent objects in the correct
|
48
|
+
# context.
|
49
|
+
res.instance_variable_set("@inspec_binding", res.instance_eval("binding"))
|
50
|
+
res
|
53
51
|
end
|
54
52
|
end
|
55
53
|
end
|
@@ -32,6 +32,13 @@ module Inspec::Plugin::V2
|
|
32
32
|
|
33
33
|
# Identify plugins that inspec is co-installed with
|
34
34
|
detect_system_plugins unless options[:omit_sys_plugins]
|
35
|
+
|
36
|
+
# Train plugins are not true InSpec plugins; we need to decorate them a
|
37
|
+
# bit more to integrate them. Wait to do this until after we know if
|
38
|
+
# they are system or user.
|
39
|
+
registry.each do |plugin_name, status|
|
40
|
+
fixup_train_plugin_status(status) if train_plugin_name?(plugin_name)
|
41
|
+
end
|
35
42
|
end
|
36
43
|
|
37
44
|
def load_all
|
@@ -48,9 +55,12 @@ module Inspec::Plugin::V2
|
|
48
55
|
begin
|
49
56
|
# We could use require, but under testing, we need to repeatedly reload the same
|
50
57
|
# plugin. However, gems only work with require (rubygems dooes not overload `load`)
|
51
|
-
|
58
|
+
case plugin_details.installation_type
|
59
|
+
when :user_gem
|
52
60
|
activate_managed_gems_for_plugin(plugin_name)
|
53
61
|
require plugin_details.entry_point
|
62
|
+
when :system_gem
|
63
|
+
require plugin_details.entry_point
|
54
64
|
else
|
55
65
|
load_path = plugin_details.entry_point
|
56
66
|
load_path += ".rb" unless plugin_details.entry_point.end_with?(".rb")
|
@@ -253,10 +263,6 @@ module Inspec::Plugin::V2
|
|
253
263
|
status.entry_point = plugin_entry[:installation_path]
|
254
264
|
end
|
255
265
|
|
256
|
-
# Train plugins are not true InSpec plugins; we need to decorate them a
|
257
|
-
# bit more to integrate them.
|
258
|
-
fixup_train_plugin_status(status) if train_plugin_name?(plugin_entry[:name])
|
259
|
-
|
260
266
|
registry[status.name] = status
|
261
267
|
end
|
262
268
|
end
|
@@ -265,6 +271,8 @@ module Inspec::Plugin::V2
|
|
265
271
|
status.api_generation = :'train-1'
|
266
272
|
if status.installation_type == :user_gem
|
267
273
|
# Activate the gem. This allows train to 'require' the gem later.
|
274
|
+
# This is not required for system gems because rubygems already has
|
275
|
+
# activated the gemspecs.
|
268
276
|
activate_managed_gems_for_plugin(status.entry_point)
|
269
277
|
end
|
270
278
|
end
|
@@ -187,8 +187,20 @@ module Inspec::Resources
|
|
187
187
|
line.scan(/-S ([^ ]+)\s?/).flatten.first.split(",")
|
188
188
|
end
|
189
189
|
|
190
|
+
# Processes the line and returns a pair of entries reflecting the 'action'
|
191
|
+
# and 'list' items.
|
192
|
+
#
|
193
|
+
# @return [Array[String,String]]
|
190
194
|
def action_list_for(line)
|
191
|
-
line.scan(/-a ([^,]+),([^ ]+)\s?/).flatten
|
195
|
+
action_list = line.scan(/-a ([^,]+),([^ ]+)\s?/).flatten
|
196
|
+
|
197
|
+
# Actions and lists can be in either order
|
198
|
+
valid_actions = %w{never always}
|
199
|
+
|
200
|
+
[
|
201
|
+
(action_list & valid_actions).first,
|
202
|
+
(action_list - valid_actions).first,
|
203
|
+
]
|
192
204
|
end
|
193
205
|
|
194
206
|
def key_for(line)
|
@@ -1,7 +1,5 @@
|
|
1
1
|
require "inspec/resources/command"
|
2
2
|
require "inspec/utils/database_helpers"
|
3
|
-
require "htmlentities"
|
4
|
-
require "rexml/document"
|
5
3
|
require "hashie/mash"
|
6
4
|
require "csv"
|
7
5
|
|
@@ -48,18 +46,15 @@ module Inspec::Resources
|
|
48
46
|
if @sqlcl_bin && inspec.command(@sqlcl_bin).exist?
|
49
47
|
@bin = @sqlcl_bin
|
50
48
|
format_options = "set sqlformat csv\nSET FEEDBACK OFF"
|
51
|
-
parser = :parse_csv_result
|
52
49
|
else
|
53
50
|
@bin = "#{@sqlplus_bin} -S"
|
54
|
-
format_options = "SET MARKUP
|
55
|
-
parser = :parse_html_result
|
51
|
+
format_options = "SET MARKUP CSV ON\nSET PAGESIZE 32000\nSET FEEDBACK OFF"
|
56
52
|
end
|
57
53
|
|
58
54
|
command = command_builder(format_options, sql)
|
59
55
|
inspec_cmd = inspec.command(command)
|
60
56
|
|
61
|
-
DatabaseHelper::SQLQueryResult.new(inspec_cmd,
|
62
|
-
send(parser, inspec_cmd.stdout))
|
57
|
+
DatabaseHelper::SQLQueryResult.new(inspec_cmd, parse_csv_result(inspec_cmd.stdout))
|
63
58
|
end
|
64
59
|
|
65
60
|
def to_s
|
@@ -86,7 +81,7 @@ module Inspec::Resources
|
|
86
81
|
elsif @su_user.nil?
|
87
82
|
%{#{sql_prefix}#{bin} "#{user}"/"#{password}"@#{host}:#{port}/#{@service} as #{@db_role}#{sql_postfix}}
|
88
83
|
else
|
89
|
-
%{su - #{@su_user} -c "env ORACLE_SID=#{@service} #{bin} / as #{@db_role}#{sql_postfix}"}
|
84
|
+
%{su - #{@su_user} -c "env ORACLE_SID=#{@service} #{@bin} / as #{@db_role}#{sql_postfix}"}
|
90
85
|
end
|
91
86
|
end
|
92
87
|
|
@@ -96,54 +91,9 @@ module Inspec::Resources
|
|
96
91
|
end
|
97
92
|
|
98
93
|
def parse_csv_result(stdout)
|
99
|
-
output = stdout.
|
100
|
-
|
101
|
-
|
102
|
-
# convert to hash
|
103
|
-
headers = table.headers
|
104
|
-
|
105
|
-
results = table.map do |row|
|
106
|
-
res = {}
|
107
|
-
headers.each do |header|
|
108
|
-
res[header.downcase] = row[header]
|
109
|
-
end
|
110
|
-
Hashie::Mash.new(res)
|
111
|
-
end
|
112
|
-
results
|
113
|
-
end
|
114
|
-
|
115
|
-
def parse_html_result(stdout)
|
116
|
-
result = stdout
|
117
|
-
# make oracle html valid html by removing the p tag, it does not include a closing tag
|
118
|
-
result = result.gsub("<p>", "").gsub("</p>", "").gsub("<br>", "")
|
119
|
-
doc = REXML::Document.new result
|
120
|
-
table = doc.elements["table"]
|
121
|
-
hash = []
|
122
|
-
unless table.nil?
|
123
|
-
rows = table.elements.to_a
|
124
|
-
headers = rows[0].elements.to_a("th").map { |entry| entry.text.strip }
|
125
|
-
rows.delete_at(0)
|
126
|
-
|
127
|
-
# iterate over each row, first row is header
|
128
|
-
hash = []
|
129
|
-
if !rows.nil? && !rows.empty?
|
130
|
-
hash = rows.map do |row|
|
131
|
-
res = {}
|
132
|
-
entries = row.elements.to_a("td")
|
133
|
-
# ignore if we have empty entries, oracle is adding th rows in between
|
134
|
-
return nil if entries.empty?
|
135
|
-
|
136
|
-
headers.each_with_index do |header, index|
|
137
|
-
# we need htmlentities since we do not have nokogiri
|
138
|
-
coder = HTMLEntities.new
|
139
|
-
val = coder.decode(entries[index].text).strip
|
140
|
-
res[header.downcase] = val
|
141
|
-
end
|
142
|
-
Hashie::Mash.new(res)
|
143
|
-
end.compact
|
144
|
-
end
|
145
|
-
end
|
146
|
-
hash
|
94
|
+
output = stdout.sub(/\r/, "").strip
|
95
|
+
converter = ->(header) { header.downcase }
|
96
|
+
CSV.parse(output, headers: true, header_converters: converter).map { |row| Hashie::Mash.new(row.to_h) }
|
147
97
|
end
|
148
98
|
end
|
149
99
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Schema Generation
|
2
|
+
|
3
|
+
These files handle the generation of JSON schema's for inspec output as yielded by `inspec schema <schema-name>`.
|
4
|
+
This schema is in the JSON Schema 4th revision spec.
|
5
|
+
|
6
|
+
## Structure
|
7
|
+
Data/schema structures shared between all outputs are located in `primitives.rb`
|
8
|
+
The files `exec_json_min.rb`, `exec_json.rb`, and `profile_json.rb` contain JSON structures for their specific output types, respectively.
|
9
|
+
The output schema is "flat" in terms of schema structure, with each "type" defined in the JSONs `definitions` block and referred to via $ref.
|
10
|
+
The logic for this is handled via the `SchemaType` class in `primitives.rb`.
|
11
|
+
All relevant dependencies are included recursively via the `dependencies` property of that class, constructed using the `build_definitions` method in `output_schema.rb`.
|
12
|
+
|
13
|
+
## Reasoning and validation
|
14
|
+
In general the first iteration of this updated schema was made by examining the output of all of the profiles in the tests directory.
|
15
|
+
All of the profiles generated by those tests successfully validate against this schema.
|
16
|
+
However, in light of potential missed properties that aren't covered by existing tests, the schema was left very non-strict.
|
17
|
+
More specifically, "additionalProperties" was left as True on all schema objects.
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require "inspec/schema/primitives"
|
2
|
+
|
3
|
+
# These type occur only when running "inspec exec --reporter json <file>".
|
4
|
+
|
5
|
+
module Inspec
|
6
|
+
module Schema
|
7
|
+
module ExecJson
|
8
|
+
# Represents a label and description, to provide human-readable info about a control
|
9
|
+
CONTROL_DESCRIPTION = Primitives::SchemaType.new("Control Description", {
|
10
|
+
"type" => "object",
|
11
|
+
"additionalProperties" => true,
|
12
|
+
"required" => %w{label data},
|
13
|
+
"properties" => {
|
14
|
+
"label" => Primitives::STRING,
|
15
|
+
"data" => Primitives::STRING,
|
16
|
+
},
|
17
|
+
}, [])
|
18
|
+
|
19
|
+
# Lists the potential values for a control result
|
20
|
+
CONTROL_RESULT_STATUS = Primitives::SchemaType.new("Control Result Status", {
|
21
|
+
"type" => "string",
|
22
|
+
"enum" => %w{passed failed skipped error},
|
23
|
+
}, [])
|
24
|
+
|
25
|
+
# Represents the statistics/result of a control"s execution
|
26
|
+
CONTROL_RESULT = Primitives::SchemaType.new("Control Result", {
|
27
|
+
"type" => "object",
|
28
|
+
"additionalProperties" => true,
|
29
|
+
"required" => %w{code_desc run_time start_time},
|
30
|
+
"properties" => {
|
31
|
+
"status" => CONTROL_RESULT_STATUS.ref,
|
32
|
+
"code_desc" => Primitives::STRING,
|
33
|
+
"run_time" => Primitives::NUMBER,
|
34
|
+
"start_time" => Primitives::STRING,
|
35
|
+
|
36
|
+
# All optional
|
37
|
+
"resource" => Primitives::STRING,
|
38
|
+
"message" => Primitives::STRING,
|
39
|
+
"skip_message" => Primitives::STRING,
|
40
|
+
"exception" => Primitives::STRING,
|
41
|
+
"backtrace" => {
|
42
|
+
"anyOf" => [
|
43
|
+
Primitives.array(Primitives::STRING),
|
44
|
+
Primitives::NULL,
|
45
|
+
],
|
46
|
+
},
|
47
|
+
},
|
48
|
+
}, [CONTROL_RESULT_STATUS])
|
49
|
+
|
50
|
+
# Represents a control produced
|
51
|
+
CONTROL = Primitives::SchemaType.new("Exec JSON Control", {
|
52
|
+
"type" => "object",
|
53
|
+
"additionalProperties" => true,
|
54
|
+
"required" => %w{id title desc impact refs tags code source_location results},
|
55
|
+
"properties" => {
|
56
|
+
"id" => Primitives.desc(Primitives::STRING, "The ID of this control"),
|
57
|
+
"title" => { "type" => %w{string null} }, # Nullable string
|
58
|
+
"desc" => { "type" => %w{string null} },
|
59
|
+
"descriptions" => Primitives.array(CONTROL_DESCRIPTION.ref),
|
60
|
+
"impact" => Primitives::IMPACT,
|
61
|
+
"refs" => Primitives.array(Primitives::REFERENCE.ref),
|
62
|
+
"tags" => Primitives::TAGS,
|
63
|
+
"code" => Primitives.desc(Primitives::STRING, "The raw source code of the control. Note that if this is an overlay control, it does not include the underlying source code"),
|
64
|
+
"source_location" => Primitives::SOURCE_LOCATION.ref,
|
65
|
+
"results" => Primitives.desc(Primitives.array(CONTROL_RESULT.ref), %q{
|
66
|
+
A list of all results of the controls describe blocks.
|
67
|
+
|
68
|
+
For instance, if in the controls code we had the following:
|
69
|
+
describe sshd_config do
|
70
|
+
its('Port') { should cmp 22 }
|
71
|
+
end
|
72
|
+
The result of this block as a ControlResult would be appended to the results list.
|
73
|
+
}),
|
74
|
+
},
|
75
|
+
}, [CONTROL_DESCRIPTION, Primitives::REFERENCE, Primitives::SOURCE_LOCATION, CONTROL_RESULT])
|
76
|
+
|
77
|
+
# Based loosely on https://www.inspec.io/docs/reference/profiles/ as of July 3, 2019
|
78
|
+
# However, concessions were made to the reality of current reporters, specifically
|
79
|
+
# with how description is omitted and version/inspec_version aren't as advertised online
|
80
|
+
PROFILE = Primitives::SchemaType.new("Exec JSON Profile", {
|
81
|
+
"type" => "object",
|
82
|
+
"additionalProperties" => true,
|
83
|
+
"required" => %w{name sha256 supports attributes groups controls},
|
84
|
+
# Name is mandatory in inspec.yml.
|
85
|
+
# supports, controls, groups, and attributes are always present, even if empty
|
86
|
+
# sha256, status, skip_message
|
87
|
+
"properties" => {
|
88
|
+
# These are provided in inspec.yml
|
89
|
+
"name" => Primitives::STRING,
|
90
|
+
"title" => Primitives::STRING,
|
91
|
+
"maintainer" => Primitives::STRING,
|
92
|
+
"copyright" => Primitives::STRING,
|
93
|
+
"copyright_email" => Primitives::STRING,
|
94
|
+
"depends" => Primitives.array(Primitives::DEPENDENCY.ref),
|
95
|
+
"parent_profile" => Primitives::STRING,
|
96
|
+
"license" => Primitives::STRING,
|
97
|
+
"summary" => Primitives::STRING,
|
98
|
+
"version" => Primitives::STRING,
|
99
|
+
"supports" => Primitives.array(Primitives::SUPPORT.ref),
|
100
|
+
"description" => Primitives::STRING,
|
101
|
+
"inspec_version" => Primitives::STRING,
|
102
|
+
|
103
|
+
# These are generated at runtime, and all except skip_message are guaranteed
|
104
|
+
"sha256" => Primitives::STRING,
|
105
|
+
"status" => Primitives::STRING,
|
106
|
+
"skip_message" => Primitives::STRING, # If skipped, why
|
107
|
+
"controls" => Primitives.array(CONTROL.ref),
|
108
|
+
"groups" => Primitives.array(Primitives::CONTROL_GROUP.ref),
|
109
|
+
"attributes" => Primitives.array(Primitives::INPUT),
|
110
|
+
},
|
111
|
+
}, [CONTROL, Primitives::CONTROL_GROUP, Primitives::DEPENDENCY, Primitives::SUPPORT])
|
112
|
+
|
113
|
+
# Result of exec json. Top level value
|
114
|
+
# TODO: Include the format of top level controls. This was omitted for lack of sufficient examples
|
115
|
+
OUTPUT = Primitives::SchemaType.new("Exec JSON Output", {
|
116
|
+
"type" => "object",
|
117
|
+
"additionalProperties" => true,
|
118
|
+
"required" => %w{platform profiles statistics version},
|
119
|
+
"properties" => {
|
120
|
+
"platform" => Primitives::PLATFORM.ref,
|
121
|
+
"profiles" => Primitives.array(PROFILE.ref),
|
122
|
+
"statistics" => Primitives::STATISTICS.ref,
|
123
|
+
"version" => Primitives::STRING,
|
124
|
+
},
|
125
|
+
}, [Primitives::PLATFORM, PROFILE, Primitives::STATISTICS])
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "inspec/schema/primitives"
|
2
|
+
|
3
|
+
# These type occur only when running "exec --reporter json-min <file>".
|
4
|
+
|
5
|
+
module Inspec
|
6
|
+
module Schema
|
7
|
+
module ExecJsonMin
|
8
|
+
# Represents a subset of the information about a control, designed for conciseness
|
9
|
+
CONTROL = Primitives::SchemaType.new("Exec JSON-MIN Control", {
|
10
|
+
"type" => "object",
|
11
|
+
"additionalProperties" => true,
|
12
|
+
"required" => %w{id profile_id profile_sha256 status code_desc},
|
13
|
+
"properties" => {
|
14
|
+
"id" => Primitives::STRING,
|
15
|
+
"profile_id" => { "type" => %w{string null} },
|
16
|
+
"profile_sha256" => Primitives::STRING,
|
17
|
+
"status" => Primitives::STRING,
|
18
|
+
"code_desc" => Primitives::STRING,
|
19
|
+
"skip_message" => Primitives::STRING,
|
20
|
+
"resource" => Primitives::STRING,
|
21
|
+
"message" => Primitives::STRING,
|
22
|
+
"exception" => Primitives::STRING,
|
23
|
+
"backtrace" => Primitives.array(Primitives::STRING),
|
24
|
+
},
|
25
|
+
}, [])
|
26
|
+
|
27
|
+
# Result of exec jsonmin. Top level value
|
28
|
+
OUTPUT = Primitives::SchemaType.new("Exec JSON-MIN output", {
|
29
|
+
"type" => "object",
|
30
|
+
"additionalProperties" => true,
|
31
|
+
"required" => %w{statistics controls version},
|
32
|
+
"properties" => {
|
33
|
+
"statistics" => Primitives::STATISTICS.ref,
|
34
|
+
"version" => Primitives::STRING,
|
35
|
+
"controls" => Primitives.array(CONTROL.ref),
|
36
|
+
},
|
37
|
+
}, [Primitives::STATISTICS, CONTROL])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "json"
|
2
|
+
require "inspec/schema/primitives"
|
3
|
+
require "inspec/schema/exec_json"
|
4
|
+
require "inspec/schema/exec_json_min"
|
5
|
+
require "inspec/schema/profile_json"
|
6
|
+
|
7
|
+
module Inspec
|
8
|
+
module Schema
|
9
|
+
module OutputSchema
|
10
|
+
# Build our definitions
|
11
|
+
def self.build_definitions(schema_type)
|
12
|
+
{
|
13
|
+
"definitions" => schema_type.all_depends.map { |t| [t.ref_name, t.body] }.to_h,
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
# Helper function to automatically bundle a type with its dependencies
|
18
|
+
def self.finalize(schema_type)
|
19
|
+
schema_type.body.merge(OutputSchema.build_definitions(schema_type))
|
20
|
+
end
|
21
|
+
|
22
|
+
# using a proc here so we can lazy load it when we need
|
23
|
+
PLATFORMS = lambda do
|
24
|
+
require "train"
|
25
|
+
Train.create("mock").connection
|
26
|
+
Train::Platforms.export
|
27
|
+
end
|
28
|
+
|
29
|
+
LIST = {
|
30
|
+
"profile-json" => OutputSchema.finalize(Schema::ProfileJson::PROFILE),
|
31
|
+
"exec-json" => OutputSchema.finalize(Schema::ExecJson::OUTPUT),
|
32
|
+
"exec-jsonmin" => OutputSchema.finalize(Schema::ExecJsonMin::OUTPUT),
|
33
|
+
"platforms" => PLATFORMS,
|
34
|
+
}.freeze
|
35
|
+
|
36
|
+
def self.names
|
37
|
+
LIST.keys
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.json(name)
|
41
|
+
if !LIST.key?(name)
|
42
|
+
raise("Cannot find schema #{name.inspect}.")
|
43
|
+
elsif LIST[name].is_a?(Proc)
|
44
|
+
v = LIST[name].call
|
45
|
+
else
|
46
|
+
v = LIST[name]
|
47
|
+
end
|
48
|
+
|
49
|
+
JSON.dump(v)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,266 @@
|
|
1
|
+
require "set"
|
2
|
+
|
3
|
+
# These elements are shared between more than one output type
|
4
|
+
|
5
|
+
module Inspec
|
6
|
+
module Schema
|
7
|
+
module Primitives
|
8
|
+
######################### Establish simple helpers for this schema ########################################
|
9
|
+
# Use this function to easily make described types
|
10
|
+
def self.desc(obj, description)
|
11
|
+
obj.merge({ "description" => description })
|
12
|
+
end
|
13
|
+
|
14
|
+
# Use this function to easily make an array of a type
|
15
|
+
def self.array(of_type)
|
16
|
+
{
|
17
|
+
"type" => "array",
|
18
|
+
"items" => of_type,
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
# This function performs some simple validation on schemas, to catch obvious missed requirements
|
23
|
+
def self.validate_schema(schema)
|
24
|
+
return if schema["type"] != "object"
|
25
|
+
raise "Objects in schema must have a \"required\" property, even if it is empty." unless schema.key?("required")
|
26
|
+
|
27
|
+
return if schema["required"].empty?
|
28
|
+
raise "An object with required properties must have a properties hash." unless schema.key?("properties")
|
29
|
+
|
30
|
+
return if Set.new(schema["required"]) <= Set.new(schema["properties"].keys)
|
31
|
+
|
32
|
+
raise "Not all required properties are present."
|
33
|
+
end
|
34
|
+
|
35
|
+
# Use this class to quickly add/use object types to/in a definition block
|
36
|
+
class SchemaType
|
37
|
+
attr_accessor :name, :depends
|
38
|
+
def initialize(name, body, dependencies)
|
39
|
+
# Validate the schema
|
40
|
+
Primitives.validate_schema(body)
|
41
|
+
# The title of the type
|
42
|
+
@name = name
|
43
|
+
# The body of the type
|
44
|
+
@body = body
|
45
|
+
# What SchemaType[]s it depends on. In essence, any thing that you .ref in the body
|
46
|
+
@depends = Set.new(dependencies)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Produce this schema types generated body.
|
50
|
+
# Use to actually define the ref!
|
51
|
+
def body
|
52
|
+
@body.merge({
|
53
|
+
"title" => @name,
|
54
|
+
})
|
55
|
+
end
|
56
|
+
|
57
|
+
# Formats this to have a JSON pointer compatible title
|
58
|
+
def ref_name
|
59
|
+
@name.gsub(/\s+/, "_")
|
60
|
+
end
|
61
|
+
|
62
|
+
# Yields this type as a json schema ref
|
63
|
+
def ref
|
64
|
+
{ "$ref" => "#/definitions/#{ref_name}" }
|
65
|
+
end
|
66
|
+
|
67
|
+
# Recursively acquire all depends for this schema. Return them sorted by name
|
68
|
+
def all_depends
|
69
|
+
result = @depends
|
70
|
+
# Fetch all from children
|
71
|
+
@depends.each do |nested_type|
|
72
|
+
# Yes, converting back to set here does some duplicate sorting.
|
73
|
+
# But here, performance really isn't our concern.
|
74
|
+
result += Set.new(nested_type.all_depends)
|
75
|
+
end
|
76
|
+
# Return the results as a sorted array
|
77
|
+
Array(result).sort_by(&:name)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
######################### Establish basic type shorthands for this schema ########################################
|
82
|
+
# These three are essentially primitives, used as shorthand
|
83
|
+
OBJECT = { "type" => "object", "additionalProperties" => true }.freeze
|
84
|
+
NUMBER = { "type" => "number" }.freeze
|
85
|
+
STRING = { "type" => "string" }.freeze
|
86
|
+
NULL = { "type" => "null" }.freeze
|
87
|
+
|
88
|
+
# We might eventually enforce string format stuff on this
|
89
|
+
URL = { "type" => "string" }.freeze
|
90
|
+
|
91
|
+
# A controls tags can have any number of properties, and any sorts of values
|
92
|
+
TAGS = { "type" => "object", "additionalProperties" => true }.freeze
|
93
|
+
|
94
|
+
# Attributes/Inputs specify the inputs to a profile.
|
95
|
+
INPUT = { "type" => "object", "additionalProperties" => true }.freeze
|
96
|
+
|
97
|
+
# Within a control file, impacts can be numeric 0-1 or string in [none,low,medium,high,critical]
|
98
|
+
# However, when they are output, the string types are automatically converted as follows:
|
99
|
+
# none -> 0 to 0.01
|
100
|
+
# low -> 0.01 to 0.4
|
101
|
+
# medium -> 0.4 to 0.7
|
102
|
+
# high -> 0.7 to 0.9
|
103
|
+
# Critical -> 0.9 to 1.0 (inclusive)
|
104
|
+
IMPACT = {
|
105
|
+
"type" => "number",
|
106
|
+
"minimum" => 0.0,
|
107
|
+
"maximum" => 1.0,
|
108
|
+
}.freeze
|
109
|
+
|
110
|
+
# A status for a control
|
111
|
+
STATUS = {
|
112
|
+
"type" => "string",
|
113
|
+
"enum" => %w{passed failed skipped error},
|
114
|
+
}.freeze
|
115
|
+
|
116
|
+
######################### Establish inspec types common to several schemas helpers for this schema #######################################
|
117
|
+
|
118
|
+
# We use "title" to name the type.
|
119
|
+
# and "description" (via the describe function) to describe its particular usage
|
120
|
+
# Summary item containing run statistics about a subset of the controls
|
121
|
+
STATISTIC_ITEM = SchemaType.new("Statistic Block", {
|
122
|
+
"type" => "object",
|
123
|
+
"additionalProperties" => true,
|
124
|
+
"required" => ["total"],
|
125
|
+
"properties" => {
|
126
|
+
"total" => desc(NUMBER, "Total number of controls (in this category) for this inspec execution."),
|
127
|
+
},
|
128
|
+
}, [])
|
129
|
+
|
130
|
+
# Bundles several results statistics, representing distinct groups of controls
|
131
|
+
STATISTIC_GROUPING = SchemaType.new("Statistic Hash", {
|
132
|
+
"type" => "object",
|
133
|
+
"additionalProperties" => true,
|
134
|
+
"required" => [],
|
135
|
+
"properties" => {
|
136
|
+
"passed" => STATISTIC_ITEM.ref,
|
137
|
+
"skipped" => STATISTIC_ITEM.ref,
|
138
|
+
"failed" => STATISTIC_ITEM.ref,
|
139
|
+
},
|
140
|
+
}, [STATISTIC_ITEM])
|
141
|
+
|
142
|
+
# Contains statistics of an exec run.
|
143
|
+
STATISTICS = SchemaType.new("Statistics", {
|
144
|
+
"type" => "object",
|
145
|
+
"additionalProperties" => true,
|
146
|
+
"required" => ["duration"],
|
147
|
+
"properties" => {
|
148
|
+
"duration" => desc(NUMBER, "How long (in seconds) this inspec exec ran for."),
|
149
|
+
"controls" => desc(STATISTIC_GROUPING.ref, "Breakdowns of control statistics by result"),
|
150
|
+
},
|
151
|
+
}, [STATISTIC_GROUPING])
|
152
|
+
|
153
|
+
# Profile dependencies
|
154
|
+
DEPENDENCY = SchemaType.new("Dependency", {
|
155
|
+
"type" => "object",
|
156
|
+
"additionalProperties" => true, # Weird stuff shows up here sometimes
|
157
|
+
"required" => [], # Mysteriously even in a run profile we can have no status
|
158
|
+
"properties" => {
|
159
|
+
"name" => STRING,
|
160
|
+
"url" => URL,
|
161
|
+
"branch" => STRING,
|
162
|
+
"path" => STRING,
|
163
|
+
"skip_message" => STRING,
|
164
|
+
"status" => STRING,
|
165
|
+
"git" => URL,
|
166
|
+
"supermarket" => STRING,
|
167
|
+
"compliance" => STRING,
|
168
|
+
},
|
169
|
+
}, [])
|
170
|
+
|
171
|
+
# Represents the platform the test was run on
|
172
|
+
PLATFORM = SchemaType.new("Platform", {
|
173
|
+
"type" => "object",
|
174
|
+
"additionalProperties" => true,
|
175
|
+
"required" => %w{name release},
|
176
|
+
"properties" => {
|
177
|
+
"name" => desc(STRING, "The name of the platform this was run on."),
|
178
|
+
"release" => desc(STRING, "The version of the platform this was run on."),
|
179
|
+
"target_id" => STRING,
|
180
|
+
},
|
181
|
+
}, [])
|
182
|
+
|
183
|
+
# Explains what software ran the inspec profile/made this file. Typically inspec but could in theory be a different software
|
184
|
+
GENERATOR = SchemaType.new("Generator", {
|
185
|
+
"type" => "object",
|
186
|
+
"additionalProperties" => true,
|
187
|
+
"required" => %w{name version},
|
188
|
+
"properties" => {
|
189
|
+
"name" => desc(STRING, "The name of the software that generated this report."),
|
190
|
+
"version" => desc(STRING, "The version of the software that generated this report."),
|
191
|
+
},
|
192
|
+
}, [])
|
193
|
+
|
194
|
+
# Occurs from "exec --reporter json" and "inspec json"
|
195
|
+
# Denotes what file this control comes from, and where within
|
196
|
+
SOURCE_LOCATION = SchemaType.new("Source Location", {
|
197
|
+
"type" => "object",
|
198
|
+
"additionalProperties" => true,
|
199
|
+
"properties" => {
|
200
|
+
"ref" => desc(STRING, "Path to the file that this statement originates from"),
|
201
|
+
"line" => desc(NUMBER, "The line at which this statement is located in the file"),
|
202
|
+
},
|
203
|
+
"required" => %w{ref line},
|
204
|
+
}, [])
|
205
|
+
|
206
|
+
# References an external document
|
207
|
+
REFERENCE = SchemaType.new("Reference", {
|
208
|
+
# Needs at least one of title (ref), url, or uri.
|
209
|
+
"anyOf" => [
|
210
|
+
{
|
211
|
+
"type" => "object",
|
212
|
+
"required" => ["ref"],
|
213
|
+
"properties" => { "ref" => STRING },
|
214
|
+
},
|
215
|
+
{
|
216
|
+
"type" => "object",
|
217
|
+
"required" => ["url"],
|
218
|
+
"properties" => { "url" => STRING },
|
219
|
+
},
|
220
|
+
{
|
221
|
+
"type" => "object",
|
222
|
+
"required" => ["uri"],
|
223
|
+
"properties" => { "uri" => STRING },
|
224
|
+
},
|
225
|
+
# I am of the opinion that this is just an error in the codebase itself. See profiles/wrapper-override to uncover new mysteries!
|
226
|
+
{
|
227
|
+
"type" => "object",
|
228
|
+
"required" => ["ref"],
|
229
|
+
"properties" => { "ref" => array(OBJECT) },
|
230
|
+
|
231
|
+
},
|
232
|
+
],
|
233
|
+
}, [])
|
234
|
+
|
235
|
+
# Represents a group of controls within a profile/.rb file
|
236
|
+
CONTROL_GROUP = SchemaType.new("Control Group", {
|
237
|
+
"type" => "object",
|
238
|
+
"additionalProperties" => true,
|
239
|
+
"required" => %w{id controls},
|
240
|
+
"properties" => {
|
241
|
+
"id" => desc(STRING, "The unique identifier of the group"),
|
242
|
+
"title" => desc({ type: %w{string null} }, "The name of the group"),
|
243
|
+
"controls" => desc(array(STRING), "The control IDs in this group"),
|
244
|
+
},
|
245
|
+
}, [])
|
246
|
+
|
247
|
+
# Occurs from "inspec exec --reporter json" and "inspec json"
|
248
|
+
# Represents a platfrom or group of platforms that this profile supports
|
249
|
+
SUPPORT = SchemaType.new("Supported Platform", {
|
250
|
+
"type" => "object",
|
251
|
+
"additionalProperties" => true, # NOTE: This should really be false, and inspec should validate profiles to ensure people don't make dumb mistakes like platform_family
|
252
|
+
"required" => [],
|
253
|
+
"properties" => {
|
254
|
+
"platform-family" => STRING,
|
255
|
+
"platform-name" => STRING,
|
256
|
+
"platform" => STRING,
|
257
|
+
"release" => STRING,
|
258
|
+
# os-* supports are being deprecated
|
259
|
+
"os-family" => STRING,
|
260
|
+
"os-name" => STRING,
|
261
|
+
},
|
262
|
+
}, [])
|
263
|
+
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "inspec/schema/primitives"
|
2
|
+
|
3
|
+
# These type occur only when running "inspec json <file>".
|
4
|
+
|
5
|
+
module Inspec
|
6
|
+
module Schema
|
7
|
+
module ProfileJson
|
8
|
+
# Represents descriptions. Can have any string => string pairing
|
9
|
+
CONTROL_DESCRIPTIONS = Primitives::SchemaType.new("Profile JSON Control Descriptions", {
|
10
|
+
"type" => "object",
|
11
|
+
"aditionalProperties" => Primitives::STRING,
|
12
|
+
"required" => [],
|
13
|
+
}, [])
|
14
|
+
|
15
|
+
# Represents a control that hasn't been run
|
16
|
+
# Differs slightly from a normal control, in that it lacks results, and its descriptions are different
|
17
|
+
CONTROL = Primitives::SchemaType.new("Profile JSON Control", {
|
18
|
+
"type" => "object",
|
19
|
+
"additionalProperties" => true,
|
20
|
+
"required" => %w{id title desc impact tags code},
|
21
|
+
"properties" => {
|
22
|
+
"id" => Primitives.desc(Primitives::STRING, "The ID of this control"),
|
23
|
+
"title" => { "type" => %w{string null} },
|
24
|
+
"desc" => { "type" => %w{string null} },
|
25
|
+
"descriptions" => CONTROL_DESCRIPTIONS.ref,
|
26
|
+
"impact" => Primitives::IMPACT,
|
27
|
+
"refs" => Primitives.array(Primitives::REFERENCE.ref),
|
28
|
+
"tags" => Primitives::TAGS,
|
29
|
+
"code" => Primitives.desc(Primitives::STRING, "The raw source code of the control. Note that if this is an overlay control, it does not include the underlying source code"),
|
30
|
+
"source_location" => Primitives::SOURCE_LOCATION.ref,
|
31
|
+
},
|
32
|
+
}, [CONTROL_DESCRIPTIONS, Primitives::REFERENCE, Primitives::SOURCE_LOCATION])
|
33
|
+
|
34
|
+
# A profile that has not been run.
|
35
|
+
PROFILE = Primitives::SchemaType.new("Profile JSON Profile", {
|
36
|
+
"type" => "object",
|
37
|
+
"additionalProperties" => true, # Anything in the yaml will be put in here. LTTODO: Make this stricter!
|
38
|
+
"required" => %w{name supports controls groups sha256},
|
39
|
+
"properties" => {
|
40
|
+
"name" => Primitives::STRING,
|
41
|
+
"supports" => Primitives.array(Primitives::SUPPORT.ref),
|
42
|
+
"controls" => Primitives.array(CONTROL.ref),
|
43
|
+
"groups" => Primitives.array(Primitives::CONTROL_GROUP.ref),
|
44
|
+
"inputs" => Primitives.array(Primitives::INPUT),
|
45
|
+
"sha256" => Primitives::STRING,
|
46
|
+
"status" => Primitives::STRING,
|
47
|
+
"generator" => Primitives::GENERATOR.ref,
|
48
|
+
"version" => Primitives::STRING,
|
49
|
+
|
50
|
+
# Other properties possible in inspec docs, but that aren"t guaranteed
|
51
|
+
"title" => Primitives::STRING,
|
52
|
+
"maintainer" => Primitives::STRING,
|
53
|
+
"copyright" => Primitives::STRING,
|
54
|
+
"copyright_email" => Primitives::STRING,
|
55
|
+
"depends" => Primitives.array(Primitives::DEPENDENCY.ref), # Can have depends, but NOT a parentprofile
|
56
|
+
},
|
57
|
+
}, [Primitives::SUPPORT, CONTROL, Primitives::CONTROL_GROUP, Primitives::DEPENDENCY, Primitives::GENERATOR])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Inspec
|
2
|
+
|
3
|
+
# Heuristics to determine how InSpec was installed.
|
4
|
+
module InstallContextHelpers
|
5
|
+
|
6
|
+
def guess_install_context
|
7
|
+
# These all work by simple path recognition
|
8
|
+
return "chef-workstation" if chef_workstation_install?
|
9
|
+
return "omnibus" if omnibus_install?
|
10
|
+
return "chefdk" if chefdk_install?
|
11
|
+
return "habitat" if habitat_install?
|
12
|
+
|
13
|
+
# Order matters here - gem mode is easily mistaken for one of the above
|
14
|
+
return "docker" if docker_install?
|
15
|
+
return "rubygem" if rubygem_install?
|
16
|
+
|
17
|
+
return "source" if source_install?
|
18
|
+
|
19
|
+
"unknown"
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def chef_workstation_install?
|
25
|
+
!!(src_root.start_with?("/opt/chef-workstation") || src_root.start_with?("C:/opscode/chef-workstation"))
|
26
|
+
end
|
27
|
+
|
28
|
+
def chefdk_install?
|
29
|
+
!!(src_root.start_with?("/opt/chef-dk") || src_root.start_with?("C:/opscode/chef-dk"))
|
30
|
+
end
|
31
|
+
|
32
|
+
def docker_install?
|
33
|
+
# Our docker image is based on alpine. This could be easily fooled.
|
34
|
+
!!(rubygem_install? && path_exist?("/etc/alpine-release")) && path_exist?("/.dockerenv")
|
35
|
+
end
|
36
|
+
|
37
|
+
def habitat_install?
|
38
|
+
!!src_root.match(%r{hab/pkgs/chef/inspec/\d+\.\d+\.\d+/\d{14}})
|
39
|
+
end
|
40
|
+
|
41
|
+
def omnibus_install?
|
42
|
+
!!(src_root.start_with?("/opt/inspec") || src_root.start_with?("C:/opscode/inspec"))
|
43
|
+
end
|
44
|
+
|
45
|
+
def rubygem_install?
|
46
|
+
!!src_root.match(%r{gems/inspec-\d+\.\d+\.\d+})
|
47
|
+
end
|
48
|
+
|
49
|
+
def source_install?
|
50
|
+
# These are a couple of examples of dirs removed during packaging
|
51
|
+
%w{habitat test}.all? do |devdir|
|
52
|
+
path_exist?("#{src_root}/#{devdir}")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def path_exist?(path)
|
57
|
+
File.exist? path
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/inspec/version.rb
CHANGED
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.18.
|
4
|
+
version: 4.18.97
|
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: 2020-02-
|
11
|
+
date: 2020-02-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef-telemetry
|
@@ -65,19 +65,19 @@ dependencies:
|
|
65
65
|
- !ruby/object:Gem::Version
|
66
66
|
version: '2.0'
|
67
67
|
- !ruby/object:Gem::Dependency
|
68
|
-
name:
|
68
|
+
name: json_schemer
|
69
69
|
requirement: !ruby/object:Gem::Requirement
|
70
70
|
requirements:
|
71
71
|
- - "~>"
|
72
72
|
- !ruby/object:Gem::Version
|
73
|
-
version:
|
73
|
+
version: 0.2.1
|
74
74
|
type: :runtime
|
75
75
|
prerelease: false
|
76
76
|
version_requirements: !ruby/object:Gem::Requirement
|
77
77
|
requirements:
|
78
78
|
- - "~>"
|
79
79
|
- !ruby/object:Gem::Version
|
80
|
-
version:
|
80
|
+
version: 0.2.1
|
81
81
|
- !ruby/object:Gem::Dependency
|
82
82
|
name: method_source
|
83
83
|
requirement: !ruby/object:Gem::Requirement
|
@@ -612,6 +612,12 @@ files:
|
|
612
612
|
- lib/inspec/runner_rspec.rb
|
613
613
|
- lib/inspec/runtime_profile.rb
|
614
614
|
- lib/inspec/schema.rb
|
615
|
+
- lib/inspec/schema/README.md
|
616
|
+
- lib/inspec/schema/exec_json.rb
|
617
|
+
- lib/inspec/schema/exec_json_min.rb
|
618
|
+
- lib/inspec/schema/output_schema.rb
|
619
|
+
- lib/inspec/schema/primitives.rb
|
620
|
+
- lib/inspec/schema/profile_json.rb
|
615
621
|
- lib/inspec/secrets.rb
|
616
622
|
- lib/inspec/secrets/yaml.rb
|
617
623
|
- lib/inspec/shell.rb
|
@@ -634,6 +640,7 @@ files:
|
|
634
640
|
- lib/inspec/utils/filter_array.rb
|
635
641
|
- lib/inspec/utils/find_files.rb
|
636
642
|
- lib/inspec/utils/hash.rb
|
643
|
+
- lib/inspec/utils/install_context.rb
|
637
644
|
- lib/inspec/utils/json_log.rb
|
638
645
|
- lib/inspec/utils/modulator.rb
|
639
646
|
- lib/inspec/utils/nginx_parser.rb
|