inspec-core 4.18.85 → 4.18.97
Sign up to get free protection for your applications and to get access to all the features.
- 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
|