inspec-core 4.38.9 → 4.41.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 17449ad4c9680511a8fc11c6fdb11d9ece550a7942c9e734c95eac0d41913d9f
4
- data.tar.gz: ae5055ccc9bebd1aed4f22da4ad4dcd1be31e1bd2b5707e7b5fb088c916eda08
3
+ metadata.gz: ccadabfe4c0ecceecb305842e1874255ce4797a8df92e9d1d940bfe52f4b2dbb
4
+ data.tar.gz: 8bed2e86c15c05fcd6ee5974e1167aab1f2ab6c2d321a6f802af738594fafe5b
5
5
  SHA512:
6
- metadata.gz: 6cec299ca48d7ca4c3fb9b3eecc79c8687541fbd83fc79e837ed13d2abb4bcb861f747782a68bf90f7e1083443a671079a1368a97e9f552e249e456616a92059
7
- data.tar.gz: 287e2d79dbc494c83d6f8b8046e0f9c54632c5a13ec75ac69b603bdf9fe9b6a89ff86c9c8f025f7e04372490adb1ffa5a5a7fc10f3ecab1e7fabd70f71f6767d
6
+ metadata.gz: ac9a9e7a80179eaa6f1a77ff4fd4aa4505a39ce389a655bdf853caeece477c58ea7ef46db749cf54a11c2e5dff5e62b09fdd950caac396ffbab4640183549924
7
+ data.tar.gz: 613c20973b4b10202fe0d0aac0e53b65cb0cb201150b93665304f0a5f7d4341981768cc799865bb3d7b9ad6b9afa93f782a9651d88001001b899d85b4521e1b6
@@ -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
- if control_exist_in_controls_list?(id) || controls_list_empty?
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) || controls_list_empty?
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
@@ -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(include_list = @controls)
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
 
@@ -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
 
@@ -1,3 +1,3 @@
1
1
  module Inspec
2
- VERSION = "4.38.9".freeze
2
+ VERSION = "4.41.2".freeze
3
3
  end
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.38.9
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-07-22 00:00:00.000000000 Z
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