inspec-core 4.38.9 → 4.41.2
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 +2 -0
- data/lib/inspec/cli.rb +2 -0
- data/lib/inspec/control_eval_context.rb +41 -2
- data/lib/inspec/profile.rb +26 -1
- data/lib/inspec/resources.rb +3 -0
- data/lib/inspec/resources/mongodb_session.rb +88 -0
- data/lib/inspec/resources/opa.rb +23 -0
- data/lib/inspec/resources/opa_api.rb +39 -0
- data/lib/inspec/resources/opa_cli.rb +43 -0
- data/lib/inspec/runner.rb +2 -0
- data/lib/inspec/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ccadabfe4c0ecceecb305842e1874255ce4797a8df92e9d1d940bfe52f4b2dbb
|
4
|
+
data.tar.gz: 8bed2e86c15c05fcd6ee5974e1167aab1f2ab6c2d321a6f802af738594fafe5b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac9a9e7a80179eaa6f1a77ff4fd4aa4505a39ce389a655bdf853caeece477c58ea7ef46db749cf54a11c2e5dff5e62b09fdd950caac396ffbab4640183549924
|
7
|
+
data.tar.gz: 613c20973b4b10202fe0d0aac0e53b65cb0cb201150b93665304f0a5f7d4341981768cc799865bb3d7b9ad6b9afa93f782a9651d88001001b899d85b4521e1b6
|
data/lib/inspec/base_cli.rb
CHANGED
@@ -136,6 +136,8 @@ module Inspec
|
|
136
136
|
profile_options
|
137
137
|
option :controls, type: :array,
|
138
138
|
desc: "A list of control names to run, or a list of /regexes/ to match against control names. Ignore all other tests."
|
139
|
+
option :tags, type: :array,
|
140
|
+
desc: "A list of tags names that are part of controls to filter and run controls, or a list of /regexes/ to match against tags names of controls. Ignore all other tests."
|
139
141
|
option :reporter, type: :array,
|
140
142
|
banner: "one two:/output/file/path",
|
141
143
|
desc: "Enable one or more output reporters: cli, documentation, html, progress, json, json-min, json-rspec, junit, yaml"
|
data/lib/inspec/cli.rb
CHANGED
@@ -65,6 +65,8 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
65
65
|
desc: "Save the created profile to a path"
|
66
66
|
option :controls, type: :array,
|
67
67
|
desc: "A list of controls to include. Ignore all other tests."
|
68
|
+
option :tags, type: :array,
|
69
|
+
desc: "A list of tags to filter controls and include only those. Ignore all other tests."
|
68
70
|
profile_options
|
69
71
|
def json(target)
|
70
72
|
require "json" unless defined?(JSON)
|
@@ -53,12 +53,23 @@ module Inspec
|
|
53
53
|
|
54
54
|
def control(id, opts = {}, &block)
|
55
55
|
opts[:skip_only_if_eval] = @skip_only_if_eval
|
56
|
-
|
56
|
+
tag_ids = control_tags(&block)
|
57
|
+
if (controls_list_empty? && tags_list_empty?) || control_exist_in_controls_list?(id) || tag_exist_in_control_tags?(tag_ids)
|
57
58
|
register_control(Inspec::Rule.new(id, profile_id, resources_dsl, opts, &block))
|
58
59
|
end
|
59
60
|
end
|
61
|
+
|
60
62
|
alias rule control
|
61
63
|
|
64
|
+
def control_tags(&block)
|
65
|
+
tag_source = block.source.split("\n").select { |src| src.split.first.eql?("tag") }
|
66
|
+
tag_source = tag_source.map { |src| src.sub("tag", "").strip }.map { |src| src.split(",").map { |final_src| final_src.sub(/([^:]*):/, "") } }.flatten
|
67
|
+
output = tag_source.map { |src| src.sub(/\[|\]/, "") }.map { |src| instance_eval(src) }
|
68
|
+
output.compact.uniq
|
69
|
+
rescue
|
70
|
+
[]
|
71
|
+
end
|
72
|
+
|
62
73
|
# Describe allows users to write rspec-like bare describe
|
63
74
|
# blocks without declaring an inclosing control. Here, we
|
64
75
|
# generate a control for them automatically and then execute
|
@@ -74,7 +85,7 @@ module Inspec
|
|
74
85
|
res = describe(*args, &block)
|
75
86
|
end
|
76
87
|
|
77
|
-
if control_exist_in_controls_list?(id)
|
88
|
+
if controls_list_empty? || control_exist_in_controls_list?(id)
|
78
89
|
register_control(rule, &block)
|
79
90
|
end
|
80
91
|
|
@@ -187,11 +198,19 @@ module Inspec
|
|
187
198
|
!@conf.empty? && @conf.key?("profile") && !@conf["profile"].include_controls_list.empty?
|
188
199
|
end
|
189
200
|
|
201
|
+
def profile_tag_config_exist?
|
202
|
+
!@conf.empty? && @conf.key?("profile") && !@conf["profile"].include_tags_list.empty?
|
203
|
+
end
|
204
|
+
|
190
205
|
# Returns true if configuration hash is empty or configuration hash does not have the list of controls that needs to be included
|
191
206
|
def controls_list_empty?
|
192
207
|
!@conf.empty? && @conf.key?("profile") && @conf["profile"].include_controls_list.empty? || @conf.empty?
|
193
208
|
end
|
194
209
|
|
210
|
+
def tags_list_empty?
|
211
|
+
!@conf.empty? && @conf.key?("profile") && @conf["profile"].include_tags_list.empty? || @conf.empty?
|
212
|
+
end
|
213
|
+
|
195
214
|
# Check if the given control exist in the --controls option
|
196
215
|
def control_exist_in_controls_list?(id)
|
197
216
|
id_exist_in_list = false
|
@@ -203,5 +222,25 @@ module Inspec
|
|
203
222
|
end
|
204
223
|
id_exist_in_list
|
205
224
|
end
|
225
|
+
|
226
|
+
# Check if the given control exist in the --tags option
|
227
|
+
def tag_exist_in_control_tags?(tag_ids)
|
228
|
+
tag_option_matches_with_list = false
|
229
|
+
if !tag_ids.empty? && !tag_ids.nil? && profile_tag_config_exist?
|
230
|
+
tag_option_matches_with_list = !(tag_ids & @conf["profile"].include_tags_list).empty?
|
231
|
+
unless tag_option_matches_with_list
|
232
|
+
@conf["profile"].include_tags_list.any? do |inclusion|
|
233
|
+
# Try to see if the inclusion is a regex, and if it matches
|
234
|
+
if inclusion.is_a?(Regexp)
|
235
|
+
tag_ids.each do |id|
|
236
|
+
tag_option_matches_with_list = (inclusion =~ id)
|
237
|
+
break if tag_option_matches_with_list
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
tag_option_matches_with_list
|
244
|
+
end
|
206
245
|
end
|
207
246
|
end
|
data/lib/inspec/profile.rb
CHANGED
@@ -87,6 +87,7 @@ module Inspec
|
|
87
87
|
@logger = options[:logger] || Logger.new(nil)
|
88
88
|
@locked_dependencies = options[:dependencies]
|
89
89
|
@controls = options[:controls] || []
|
90
|
+
@tags = options[:tags] || []
|
90
91
|
@writable = options[:writable] || false
|
91
92
|
@profile_id = options[:id]
|
92
93
|
@profile_name = options[:profile_name]
|
@@ -206,7 +207,7 @@ module Inspec
|
|
206
207
|
@params ||= load_params
|
207
208
|
end
|
208
209
|
|
209
|
-
def collect_tests
|
210
|
+
def collect_tests
|
210
211
|
unless @tests_collected || failed?
|
211
212
|
return unless supports_platform?
|
212
213
|
|
@@ -253,6 +254,30 @@ module Inspec
|
|
253
254
|
included_controls
|
254
255
|
end
|
255
256
|
|
257
|
+
# This creates the list of controls to be filtered by tag values provided in the --tags options
|
258
|
+
def include_tags_list
|
259
|
+
return [] if @tags.nil? || @tags.empty?
|
260
|
+
|
261
|
+
included_tags = @tags
|
262
|
+
# Check for anything that might be a regex in the list, and make it official
|
263
|
+
included_tags.each_with_index do |inclusion, index|
|
264
|
+
next if inclusion.is_a?(Regexp)
|
265
|
+
# Insist the user wrap the regex in slashes to demarcate it as a regex
|
266
|
+
next unless inclusion.start_with?("/") && inclusion.end_with?("/")
|
267
|
+
|
268
|
+
inclusion = inclusion[1..-2] # Trim slashes
|
269
|
+
begin
|
270
|
+
re = Regexp.new(inclusion)
|
271
|
+
included_tags[index] = re
|
272
|
+
rescue RegexpError => e
|
273
|
+
warn "Ignoring unparseable regex '/#{inclusion}/' in --control CLI option: #{e.message}"
|
274
|
+
included_tags[index] = nil
|
275
|
+
end
|
276
|
+
end
|
277
|
+
included_tags.compact!
|
278
|
+
included_tags
|
279
|
+
end
|
280
|
+
|
256
281
|
def load_libraries
|
257
282
|
return @runner_context if @libraries_loaded
|
258
283
|
|
data/lib/inspec/resources.rb
CHANGED
@@ -73,6 +73,7 @@ require "inspec/resources/limits_conf"
|
|
73
73
|
require "inspec/resources/login_defs"
|
74
74
|
require "inspec/resources/mongodb"
|
75
75
|
require "inspec/resources/mongodb_conf"
|
76
|
+
require "inspec/resources/mongodb_session"
|
76
77
|
require "inspec/resources/mount"
|
77
78
|
require "inspec/resources/mssql_session"
|
78
79
|
require "inspec/resources/mysql"
|
@@ -83,6 +84,8 @@ require "inspec/resources/nginx_conf"
|
|
83
84
|
require "inspec/resources/npm"
|
84
85
|
require "inspec/resources/ntp_conf"
|
85
86
|
require "inspec/resources/oneget"
|
87
|
+
require "inspec/resources/opa_cli"
|
88
|
+
require "inspec/resources/opa_api"
|
86
89
|
require "inspec/resources/oracledb_session"
|
87
90
|
require "inspec/resources/os"
|
88
91
|
require "inspec/resources/os_env"
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require "mongo"
|
2
|
+
|
3
|
+
module Inspec::Resources
|
4
|
+
class Lines
|
5
|
+
attr_reader :params
|
6
|
+
|
7
|
+
def initialize(raw, desc)
|
8
|
+
@params = raw
|
9
|
+
@desc = desc
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
@desc
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class MongodbSession < Inspec.resource(1)
|
18
|
+
name "mongodb_session"
|
19
|
+
supports platform: "unix"
|
20
|
+
supports platform: "windows"
|
21
|
+
|
22
|
+
desc "Use the mongodb_session InSpec audit resource to run MongoDB command against a MongoDB Database."
|
23
|
+
example <<~EXAMPLE
|
24
|
+
# default values:
|
25
|
+
# host: "127.0.0.1"
|
26
|
+
# port: "27017"
|
27
|
+
# auth_source - default to database name
|
28
|
+
# auth_mech - :scram
|
29
|
+
|
30
|
+
describe mongodb_session(user: "foo", password: "bar", database: "test").query(usersInfo: "ian").params["users"].first["roles"].first do
|
31
|
+
its(["role"]) { should eq "readWrite" }
|
32
|
+
end
|
33
|
+
EXAMPLE
|
34
|
+
attr_reader :user, :host, :port, :database, :params
|
35
|
+
|
36
|
+
def initialize(opts = {})
|
37
|
+
@user = opts[:user] || nil
|
38
|
+
@password = opts[:password] || nil
|
39
|
+
@host = opts[:host] || "127.0.0.1"
|
40
|
+
@port = opts[:port] || "27017"
|
41
|
+
@database = opts[:database] || nil
|
42
|
+
@auth_mech = opts[:auth_mech] || :scram
|
43
|
+
@auth_source = opts[:auth_source] || @database
|
44
|
+
@ssl = opts[:ssl] || false
|
45
|
+
@ssl_cert = opts[:ssl_cert] || nil
|
46
|
+
@ssl_key = opts[:ssl_key] || nil
|
47
|
+
@ssl_ca_cert = opts[:ssl_ca_cert] || nil
|
48
|
+
@auth_mech_properties = opts[:auth_mech_properties] || {}
|
49
|
+
@client = nil
|
50
|
+
|
51
|
+
fail_resource "Can't run MongoDB checks without authentication." unless user && @password
|
52
|
+
fail_resource "You must provide a database name for the session." unless database
|
53
|
+
|
54
|
+
create_session
|
55
|
+
end
|
56
|
+
|
57
|
+
def query(command)
|
58
|
+
raise Inspec::Exceptions::ResourceFailed, "#{resource_exception_message}" if resource_failed?
|
59
|
+
|
60
|
+
Lines.new(@client.command(command).documents.first, "MongoDB query: #{command}")
|
61
|
+
rescue => e
|
62
|
+
raise Inspec::Exceptions::ResourceFailed, "Can't run MongoDB command Error: #{e.message}"
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def create_session
|
68
|
+
raise Inspec::Exceptions::ResourceFailed, "#{resource_exception_message}" if resource_failed?
|
69
|
+
|
70
|
+
options = { user: "#{user}",
|
71
|
+
password: "#{@password}",
|
72
|
+
database: "#{database}",
|
73
|
+
auth_source: "#{@auth_source}",
|
74
|
+
auth_mech: @auth_mech,
|
75
|
+
}
|
76
|
+
options[:auth_mech_properties] = @auth_mech_properties unless @auth_mech_properties.empty?
|
77
|
+
options[:ssl] = @ssl
|
78
|
+
opitons[:ssl_key] = @ssl_key unless @ssl_key.nil?
|
79
|
+
options[:ssl_cert] = @ssl_cert unless @ssl_cert.nil?
|
80
|
+
options[:ssl_ca_cert] = @ssl_ca_cert unless @ssl_ca_cert.nil?
|
81
|
+
|
82
|
+
@client = Mongo::Client.new([ "#{host}:#{port}" ], options)
|
83
|
+
|
84
|
+
rescue => e
|
85
|
+
raise Inspec::Exceptions::ResourceFailed, "Can't run MongoDB command. Error: #{e.message}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "inspec/resources/json"
|
2
|
+
|
3
|
+
module Inspec::Resources
|
4
|
+
class Opa < JsonConfig
|
5
|
+
name "opa"
|
6
|
+
supports platform: "unix"
|
7
|
+
supports platform: "windows"
|
8
|
+
|
9
|
+
attr_reader :result
|
10
|
+
def initialize(content)
|
11
|
+
@content = content
|
12
|
+
super({ content: @content })
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def parse(content)
|
18
|
+
@content = YAML.load(content)
|
19
|
+
rescue => e
|
20
|
+
raise Inspec::Exceptions::ResourceFailed, "Unable to parse OPA query output: #{e.message}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require "inspec/resources/opa"
|
2
|
+
|
3
|
+
module Inspec::Resources
|
4
|
+
class OpaApi < Opa
|
5
|
+
name "opa_api"
|
6
|
+
supports platform: "unix"
|
7
|
+
supports platform: "windows"
|
8
|
+
|
9
|
+
def initialize(opts = {})
|
10
|
+
@url = opts[:url] || nil
|
11
|
+
@data = opts[:data] || nil
|
12
|
+
fail_resource "OPA url and data are mandatory." if @url.nil? || @url.empty? || @data.nil? || @data.empty?
|
13
|
+
@content = load_result
|
14
|
+
super(@content)
|
15
|
+
end
|
16
|
+
|
17
|
+
def allow
|
18
|
+
@content["result"]
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"OPA api"
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def load_result
|
28
|
+
raise Inspec::Exceptions::ResourceFailed, "#{resource_exception_message}" if resource_failed?
|
29
|
+
|
30
|
+
result = inspec.command("curl -X POST #{@url} -d @#{@data} -H 'Content-Type: application/json'")
|
31
|
+
if result.exit_status == 0
|
32
|
+
result.stdout.gsub("\n", "")
|
33
|
+
else
|
34
|
+
error = result.stdout + "\n" + result.stderr
|
35
|
+
raise Inspec::Exceptions::ResourceFailed, "Error while executing OPA query: #{error}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "inspec/resources/opa"
|
2
|
+
|
3
|
+
module Inspec::Resources
|
4
|
+
class OpaCli < Opa
|
5
|
+
name "opa_cli"
|
6
|
+
supports platform: "unix"
|
7
|
+
supports platform: "windows"
|
8
|
+
|
9
|
+
def initialize(opts = {})
|
10
|
+
@opa_executable_path = opts[:opa_executable_path] || "opa" # if this path is not provided then we will assume that it's been set in the ENV PATH
|
11
|
+
@policy = opts[:policy] || nil
|
12
|
+
@data = opts[:data] || nil
|
13
|
+
@query = opts[:query] || nil
|
14
|
+
if (@policy.nil? || @policy.empty?) || (@data.nil? || @data.empty?) || (@query.nil? || @query.empty?)
|
15
|
+
fail_resource "OPA policy, data and query are mandatory."
|
16
|
+
end
|
17
|
+
@content = load_result
|
18
|
+
super(@content)
|
19
|
+
end
|
20
|
+
|
21
|
+
def allow
|
22
|
+
@content["result"][0]["expressions"][0]["value"] if @content["result"][0]["expressions"][0]["text"].include?("allow")
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s
|
26
|
+
"OPA cli"
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def load_result
|
32
|
+
raise Inspec::Exceptions::ResourceFailed, "#{resource_exception_message}" if resource_failed?
|
33
|
+
|
34
|
+
result = inspec.command("#{@opa_executable_path} eval -i '#{@data}' -d '#{@policy}' '#{@query}'")
|
35
|
+
if result.exit_status == 0
|
36
|
+
result.stdout.gsub("\n", "")
|
37
|
+
else
|
38
|
+
error = result.stdout + "\n" + result.stderr
|
39
|
+
raise Inspec::Exceptions::ResourceFailed, "Error while executing OPA query: #{error}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/inspec/runner.rb
CHANGED
@@ -50,6 +50,7 @@ module Inspec
|
|
50
50
|
@conf[:logger] ||= Logger.new(nil)
|
51
51
|
@target_profiles = []
|
52
52
|
@controls = @conf[:controls] || []
|
53
|
+
@tags = @conf[:tags] || []
|
53
54
|
@depends = @conf[:depends] || []
|
54
55
|
@create_lockfile = @conf[:create_lockfile]
|
55
56
|
@cache = Inspec::Cache.new(@conf[:vendor_cache])
|
@@ -199,6 +200,7 @@ module Inspec
|
|
199
200
|
vendor_cache: @cache,
|
200
201
|
backend: @backend,
|
201
202
|
controls: @controls,
|
203
|
+
tags: @tags,
|
202
204
|
runner_conf: @conf)
|
203
205
|
raise "Could not resolve #{target} to valid input." if profile.nil?
|
204
206
|
|
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.
|
4
|
+
version: 4.41.2
|
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: 2021-
|
11
|
+
date: 2021-08-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef-telemetry
|
@@ -556,6 +556,7 @@ files:
|
|
556
556
|
- lib/inspec/resources/login_defs.rb
|
557
557
|
- lib/inspec/resources/mongodb.rb
|
558
558
|
- lib/inspec/resources/mongodb_conf.rb
|
559
|
+
- lib/inspec/resources/mongodb_session.rb
|
559
560
|
- lib/inspec/resources/mount.rb
|
560
561
|
- lib/inspec/resources/mssql_session.rb
|
561
562
|
- lib/inspec/resources/mysql.rb
|
@@ -567,6 +568,9 @@ files:
|
|
567
568
|
- lib/inspec/resources/npm.rb
|
568
569
|
- lib/inspec/resources/ntp_conf.rb
|
569
570
|
- lib/inspec/resources/oneget.rb
|
571
|
+
- lib/inspec/resources/opa.rb
|
572
|
+
- lib/inspec/resources/opa_api.rb
|
573
|
+
- lib/inspec/resources/opa_cli.rb
|
570
574
|
- lib/inspec/resources/oracledb_session.rb
|
571
575
|
- lib/inspec/resources/os.rb
|
572
576
|
- lib/inspec/resources/os_env.rb
|