inspec-core 4.41.20 → 4.46.13

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: 26a893a79810f4d3e7aeb90032bd625636c045c8edc11274dddef456d504d278
4
- data.tar.gz: 05c34cf8764889bc585a0175cfd7d7c63ef54a4c45c30d182f599de1b3ef8a56
3
+ metadata.gz: 1cc013914b6503c547eeb5fbba13ce8398cf039236b82a0422339a8b7d178649
4
+ data.tar.gz: bb763eb39cb82fa264417d15147769d9d4b3fe1dff34ac40351712a35c6dbcb3
5
5
  SHA512:
6
- metadata.gz: 6d04b25d7423b4fec6be048b8f131bfc28e90266a631829270930b8aa96a520b220c19a0d8fe463689441f67cb8d567d6163df7f56fcc27786ef72f25508dbfc
7
- data.tar.gz: f798eee0dafda728d169d34ac8a73fef9803f3a70b1b1342d395d3954420644cef3fedcc202c1dc30204bdf1b2098741831af0200b1b3758c03511f38874e9ca
6
+ metadata.gz: 492c4bbde3afe3c8be2d7640bb5e6a04f973a762aa2b541231dc61a3862d2d4d3248a49ff9b149ca66fa07eba83e1cd61260185a61fb073ba6a3cc9b542ac04f
7
+ data.tar.gz: 89b55b1c8d8da24e1266bf6e19f688d284b88b18ec36c97f3f088c6f0422ac6ae6b0ddcab867bcb174ae789fc8e5bb334ed40cfd49adb26c7c3eb401c3164123
@@ -4,7 +4,7 @@
4
4
  "groups": {
5
5
  "attrs_value_replaces_default": {
6
6
  "action": "warn",
7
- "prefix": "The 'default' option for attributes is being replaced by 'value' - please use it instead."
7
+ "prefix": "The 'default' option for inputs is being replaced by 'value' - please use it instead."
8
8
  },
9
9
  "attrs_dsl": {
10
10
  "action": "ignore",
data/lib/inspec/cli.rb CHANGED
@@ -93,7 +93,8 @@ class Inspec::InspecCLI < Inspec::BaseCLI
93
93
  end
94
94
 
95
95
  desc "check PATH", "verify all tests at the specified PATH"
96
- option :format, type: :string
96
+ option :format, type: :string,
97
+ desc: "The output format to use doc (default), json. If valid format is not provided then it will use the default."
97
98
  profile_options
98
99
  def check(path) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
99
100
  o = config
@@ -18,6 +18,7 @@ module Inspec
18
18
  attr_accessor :skip_file
19
19
  attr_accessor :profile_context
20
20
  attr_accessor :resources_dsl
21
+ attr_accessor :conf
21
22
 
22
23
  def initialize(profile_context, resources_dsl, backend, conf, dependencies, require_loader, skip_only_if_eval)
23
24
  @profile_context = profile_context
@@ -189,29 +190,24 @@ module Inspec
189
190
  @skip_file = true
190
191
  end
191
192
 
192
- private
193
-
194
- def block_location(block, alternate_caller)
195
- if block.nil?
196
- alternate_caller[/^(.+:\d+):in .+$/, 1] || "unknown"
197
- else
198
- path, line = block.source_location
199
- "#{File.basename(path)}:#{line}"
193
+ # Check if the given control exist in the --tags option
194
+ def tag_exist_in_control_tags?(tag_ids)
195
+ tag_option_matches_with_list = false
196
+ if !tag_ids.empty? && !tag_ids.nil? && profile_tag_config_exist?
197
+ tag_option_matches_with_list = !(tag_ids & @conf["profile"].include_tags_list).empty?
198
+ unless tag_option_matches_with_list
199
+ @conf["profile"].include_tags_list.any? do |inclusion|
200
+ # Try to see if the inclusion is a regex, and if it matches
201
+ if inclusion.is_a?(Regexp)
202
+ tag_ids.each do |id|
203
+ tag_option_matches_with_list = (inclusion =~ id)
204
+ break if tag_option_matches_with_list
205
+ end
206
+ end
207
+ end
208
+ end
200
209
  end
201
- end
202
-
203
- # Returns true if configuration hash is not empty and it contains the list of controls is not empty
204
- def profile_config_exist?
205
- !@conf.empty? && @conf.key?("profile") && !@conf["profile"].include_controls_list.empty?
206
- end
207
-
208
- def profile_tag_config_exist?
209
- !@conf.empty? && @conf.key?("profile") && !@conf["profile"].include_tags_list.empty?
210
- end
211
-
212
- # Returns true if configuration hash is empty or configuration hash does not have the list of controls that needs to be included
213
- def controls_list_empty?
214
- !@conf.empty? && @conf.key?("profile") && @conf["profile"].include_controls_list.empty? || @conf.empty?
210
+ tag_option_matches_with_list
215
211
  end
216
212
 
217
213
  def tags_list_empty?
@@ -230,24 +226,29 @@ module Inspec
230
226
  id_exist_in_list
231
227
  end
232
228
 
233
- # Check if the given control exist in the --tags option
234
- def tag_exist_in_control_tags?(tag_ids)
235
- tag_option_matches_with_list = false
236
- if !tag_ids.empty? && !tag_ids.nil? && profile_tag_config_exist?
237
- tag_option_matches_with_list = !(tag_ids & @conf["profile"].include_tags_list).empty?
238
- unless tag_option_matches_with_list
239
- @conf["profile"].include_tags_list.any? do |inclusion|
240
- # Try to see if the inclusion is a regex, and if it matches
241
- if inclusion.is_a?(Regexp)
242
- tag_ids.each do |id|
243
- tag_option_matches_with_list = (inclusion =~ id)
244
- break if tag_option_matches_with_list
245
- end
246
- end
247
- end
248
- end
229
+ # Returns true if configuration hash is empty or configuration hash does not have the list of controls that needs to be included
230
+ def controls_list_empty?
231
+ !@conf.empty? && @conf.key?("profile") && @conf["profile"].include_controls_list.empty? || @conf.empty?
232
+ end
233
+
234
+ private
235
+
236
+ def block_location(block, alternate_caller)
237
+ if block.nil?
238
+ alternate_caller[/^(.+:\d+):in .+$/, 1] || "unknown"
239
+ else
240
+ path, line = block.source_location
241
+ "#{File.basename(path)}:#{line}"
249
242
  end
250
- tag_option_matches_with_list
243
+ end
244
+
245
+ # Returns true if configuration hash is not empty and it contains the list of controls is not empty
246
+ def profile_config_exist?
247
+ !@conf.empty? && @conf.key?("profile") && !@conf["profile"].include_controls_list.empty?
248
+ end
249
+
250
+ def profile_tag_config_exist?
251
+ !@conf.empty? && @conf.key?("profile") && !@conf["profile"].include_tags_list.empty?
251
252
  end
252
253
  end
253
254
  end
data/lib/inspec/dsl.rb CHANGED
@@ -93,23 +93,38 @@ module Inspec::DSL
93
93
  context = dep_entry.profile.runner_context
94
94
  # if we don't want all the rules, then just make 1 pass to get all rule_IDs
95
95
  # that we want to keep from the original
96
- filter_included_controls(context, dep_entry.profile, &block) unless opts[:include_all]
96
+ if !opts[:include_all] || !(opts[:conf]["profile"].include_tags_list.empty?) || !opts[:conf]["profile"].include_controls_list.empty?
97
+ filter_included_controls(context, dep_entry.profile, opts, &block)
98
+ end
97
99
  # interpret the block and skip/modify as required
98
100
  context.load(block) if block_given?
99
101
  bind_context.add_subcontext(context)
100
102
  end
101
103
 
102
- def self.filter_included_controls(context, profile, &block)
104
+ def self.filter_included_controls(context, profile, opts, &block)
103
105
  mock = Inspec::Backend.create(Inspec::Config.mock)
104
106
  include_ctx = Inspec::ProfileContext.for_profile(profile, mock)
105
107
  include_ctx.load(block) if block_given?
108
+ include_ctx.control_eval_context.conf = opts[:conf]
109
+ control_eval_ctx = include_ctx.control_eval_context
106
110
  # remove all rules that were not registered
107
111
  context.all_rules.each do |r|
108
112
  id = Inspec::Rule.rule_id(r)
109
113
  fid = Inspec::Rule.profile_id(r) + "/" + id
110
- unless include_ctx.rules[id] || include_ctx.rules[fid]
114
+ if !opts[:include_all] && !(include_ctx.rules[id] || include_ctx.rules[fid])
111
115
  context.remove_rule(fid)
112
116
  end
117
+
118
+ unless control_eval_ctx.controls_list_empty?
119
+ # filter the dependent profile controls which are not in the --controls options list
120
+ context.remove_rule(fid) unless control_eval_ctx.control_exist_in_controls_list?(id)
121
+ end
122
+
123
+ unless control_eval_ctx.tags_list_empty?
124
+ # filter included controls using --tags
125
+ tag_ids = control_eval_ctx.control_tags(r)
126
+ context.remove_rule(fid) unless control_eval_ctx.tag_exist_in_control_tags?(tag_ids)
127
+ end
113
128
  end
114
129
  end
115
130
  end
@@ -0,0 +1,55 @@
1
+ # chrony_conf
2
+
3
+ require "inspec/utils/simpleconfig"
4
+ require "inspec/utils/file_reader"
5
+
6
+ module Inspec::Resources
7
+ class ChronyConf < Inspec.resource(1)
8
+ name "chrony_conf"
9
+ supports platform: "unix"
10
+ desc "Use the chrony_conf InSpec audit resource to test the synchronization settings defined in the chrony.conf file. This file is typically located at /etc/chrony.conf."
11
+ example <<~EXAMPLE
12
+ describe chrony_conf do
13
+ its('server') { should_not cmp nil }
14
+ its('restrict') { should include '-4 default kod notrap nomodify nopeer noquery' }
15
+ its('pool') { should include 'pool.ntp.org iburst' }
16
+ its('driftfile') { should cmp '/var/lib/ntp/drift' }
17
+ its('allow') { should cmp nil }
18
+ its('keyfile') { should cmp '/etc/chrony.keys' }
19
+ end
20
+ EXAMPLE
21
+
22
+ include FileReader
23
+
24
+ def initialize(path = nil)
25
+ @conf_path = path || "/etc/chrony.conf"
26
+ @content = read_file_content(@conf_path)
27
+ end
28
+
29
+ def method_missing(name)
30
+ param = read_params[name.to_s]
31
+ # extract first value if we have only one value in array
32
+ return param[0] if param.is_a?(Array) && (param.length == 1)
33
+
34
+ param
35
+ end
36
+
37
+ def to_s
38
+ "chrony.conf"
39
+ end
40
+
41
+ private
42
+
43
+ def read_params
44
+ return @params if defined?(@params)
45
+
46
+ # parse the file
47
+ conf = SimpleConfig.new(
48
+ @content,
49
+ assignment_regex: /^\s*(\S+)\s+(.*)\s*$/,
50
+ multiple_values: true
51
+ )
52
+ @params = conf.params
53
+ end
54
+ end
55
+ end
@@ -11,14 +11,28 @@ module Inspec::Resources
11
11
  describe csv('example.csv') do
12
12
  its('name') { should eq(['John', 'Alice']) }
13
13
  end
14
+
15
+ describe csv('example.csv', false).params do
16
+ its[[0]] { should eq (['name', 'col1', 'col2']) }
17
+ emd
14
18
  EXAMPLE
15
19
 
20
+ def initialize(path, headers = true)
21
+ @headers = headers
22
+ super(path)
23
+ end
24
+
16
25
  # override the parse method from JsonConfig
17
26
  # Assuming a header row of name,col1,col2, it will output an array of hashes like so:
18
27
  # [
19
28
  # { 'name' => 'row1', 'col1' => 'value1', 'col2' => 'value2' },
20
29
  # { 'name' => 'row2', 'col1' => 'value3', 'col2' => 'value4' }
21
30
  # ]
31
+ # When headers is set to false it will return data as array of array
32
+ # [
33
+ # ['name', col1', 'col2'],
34
+ # ['row2', 'value3', 'value4']
35
+ # ]
22
36
  def parse(content)
23
37
  require "csv" unless defined?(CSV)
24
38
 
@@ -28,10 +42,14 @@ module Inspec::Resources
28
42
  end
29
43
 
30
44
  # implicit conversion of values
31
- csv = CSV.new(content, headers: true, converters: %i{all blank_to_nil})
45
+ csv = CSV.new(content, headers: @headers, converters: %i{all blank_to_nil})
32
46
 
33
47
  # convert to hash
34
- csv.to_a.map(&:to_hash)
48
+ if @headers
49
+ csv.to_a.map(&:to_hash)
50
+ else
51
+ csv.to_a
52
+ end
35
53
  rescue => e
36
54
  raise Inspec::Exceptions::ResourceFailed, "Unable to parse CSV: #{e.message}"
37
55
  end
@@ -42,7 +60,12 @@ module Inspec::Resources
42
60
  # #value method from JsonConfig (which uses ObjectTraverser.extract_value)
43
61
  # doesn't make sense here.
44
62
  def value(key)
45
- @params.map { |x| x[key.first.to_s] }.compact
63
+ if @headers
64
+ @params.map { |x| x[key.first.to_s] }.compact
65
+ else
66
+ # when headers is set to false send the array as it is.
67
+ @params
68
+ end
46
69
  end
47
70
 
48
71
  private
@@ -0,0 +1,57 @@
1
+ module Inspec::Resources
2
+ class Ibmdb2Conf < Inspec.resource(1)
3
+ name "ibmdb2_conf"
4
+
5
+ supports platform: "unix"
6
+ supports platform: "windows"
7
+
8
+ desc "Use the ibmdb2_conf InSpec audit resource to test the configuration values of IBM Db2 database."
9
+ example <<~EXAMPLE
10
+ describe ibmdb2_conf(db2_executable_file_path: "path_to_db2_binary", db_instance: "db2inst1") do
11
+ its("output") { should_not be_empty }
12
+ its("output") { should include("Audit buffer size (4KB) (AUDIT_BUF_SZ) = 0")}
13
+ end
14
+ EXAMPLE
15
+
16
+ attr_reader :output
17
+
18
+ def initialize(opts = {})
19
+ if inspec.os.platform?("unix")
20
+ @db2_executable_file_path = opts[:db2_executable_file_path]
21
+ @db_instance = opts[:db_instance]
22
+ raise Inspec::Exceptions::ResourceFailed, "Can't connect to IBM DB2 without db2_executable_file_path, db_instance options provided." if @db2_executable_file_path.nil? || @db_instance.nil?
23
+ end
24
+ @output = run_command
25
+ end
26
+
27
+ def to_s
28
+ "IBM Db2 Conf"
29
+ end
30
+
31
+ private
32
+
33
+ def run_command
34
+ # attach to the db2 instance and get the configuration
35
+ if inspec.os.platform?("unix")
36
+ cmd = inspec.command("#{@db2_executable_file_path} attach to #{@db_instance}\; #{@db2_executable_file_path} get database manager configuration")
37
+ out = cmd.stdout + "\n" + cmd.stderr
38
+
39
+ # check if following specific error is there. Sourcing the db2profile to resolve the error.
40
+ if cmd.exit_status != 0 && out =~ /SQL10007N Message "-1390" could not be retrieved. Reason code: "3"/
41
+ cmd = inspec.command(". ~/sqllib/db2profile\; #{@db2_executable_file_path} attach to #{@db_instance}\; #{@db2_executable_file_path} get database manager configuration")
42
+ out = cmd.stdout + "\n" + cmd.stderr
43
+ end
44
+ elsif inspec.os.platform?("windows")
45
+ # set-item command set the powershell to run the db2 commands.
46
+ cmd = inspec.command("set-item -path env:DB2CLP -value \"**$$**\"\; db2 get database manager configuration")
47
+ out = cmd.stdout + "\n" + cmd.stderr
48
+ end
49
+
50
+ if cmd.exit_status != 0 || out =~ /Can't connect to IBM Db2 server/ || out.downcase =~ /^error:.*/
51
+ raise Inspec::Exceptions::ResourceFailed, "IBM Db2 query with error: #{out}"
52
+ else
53
+ cmd.stdout.gsub(/\n|\r/, ",").split(",").reject { |n| n.nil? || n.empty? }.map { |n| n.strip.gsub!(/\s+/, " ") }
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,69 @@
1
+ module Inspec::Resources
2
+ class Lines
3
+ attr_reader :output
4
+
5
+ def initialize(raw, desc)
6
+ @output = raw
7
+ @desc = desc
8
+ end
9
+
10
+ def to_s
11
+ @desc
12
+ end
13
+ end
14
+
15
+ class Ibmdb2Session < Inspec.resource(1)
16
+ name "ibmdb2_session"
17
+
18
+ supports platform: "unix"
19
+ supports platform: "windows"
20
+
21
+ desc "Use the ibmdb2_session InSpec audit resource to test SQL commands run against a IBM Db2 database."
22
+ example <<~EXAMPLE
23
+ describe ibmdb2_session(db2_executable_file_path: "path_to_db2_binary", db_instance: "db2inst1", db_name: "sample").query('list database directory') do
24
+ its('output') { should_not match(/sample/) }
25
+ end
26
+ EXAMPLE
27
+
28
+ def initialize(opts = {})
29
+ @db_name = opts[:db_name]
30
+ if inspec.os.platform?("unix")
31
+ @db2_executable_file_path = opts[:db2_executable_file_path]
32
+ @db_instance = opts[:db_instance]
33
+ raise Inspec::Exceptions::ResourceFailed, "Can't run IBM DB2 queries without db2_executable_file_path, db_instance, db_name options provided." if @db2_executable_file_path.nil? || @db_instance.nil? || @db_name.nil?
34
+ elsif inspec.os.platform?("windows")
35
+ raise Inspec::Exceptions::ResourceFailed, "Can't run IBM DB2 queries without db_name option provided." if @db_name.nil?
36
+ end
37
+ end
38
+
39
+ def query(q)
40
+ raise Inspec::Exceptions::ResourceFailed, "#{resource_exception_message}" if resource_failed?
41
+
42
+ if inspec.os.platform?("unix")
43
+ # connect to the db and query on the database
44
+ cmd = inspec.command("#{@db2_executable_file_path} attach to #{@db_instance}\; #{@db2_executable_file_path} connect to #{@db_name}\; #{@db2_executable_file_path} #{q}\;")
45
+ out = cmd.stdout + "\n" + cmd.stderr
46
+
47
+ # check if following specific error is there. Sourcing the db2profile to resolve the error.
48
+ if cmd.exit_status != 0 && out =~ /SQL10007N Message "-1390" could not be retrieved. Reason code: "3"/
49
+ cmd = inspec.command(". ~/sqllib/db2profile\; #{@db2_executable_file_path} attach to #{@db_instance}\; #{@db2_executable_file_path} connect to #{@db_name}\; #{@db2_executable_file_path} #{q}\;")
50
+ out = cmd.stdout + "\n" + cmd.stderr
51
+ end
52
+ elsif inspec.os.platform?("windows")
53
+ # set-item command set the powershell to run the db2 commands.
54
+ cmd = inspec.command("set-item -path env:DB2CLP -value \"**$$**\"\; db2 connect to #{@db_name}\; db2 #{q}\;")
55
+ out = cmd.stdout + "\n" + cmd.stderr
56
+ end
57
+
58
+ if cmd.exit_status != 0 || out =~ /Can't connect to IBM Db2 / || out.downcase =~ /^error:.*/
59
+ raise Inspec::Exceptions::ResourceFailed, "IBM Db2 connection error: #{out}"
60
+ else
61
+ Lines.new(cmd.stdout.strip, "IBM Db2 Query: #{q}")
62
+ end
63
+ end
64
+
65
+ def to_s
66
+ "IBM Db2 Session"
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,48 @@
1
+ require "inspec/resources/mssql_session"
2
+
3
+ module Inspec::Resources
4
+ class MssqlSysConf < Inspec.resource(1)
5
+ name "mssql_sys_conf"
6
+ supports platform: "windows"
7
+ supports platform: "debian"
8
+ supports platform: "redhat"
9
+ supports platform: "suse"
10
+
11
+ desc "Use the mssql_sys_conf InSpec audit resource to test the database system configurations for Mssql DB"
12
+ example <<~EXAMPLE
13
+ describe mssql_sys_conf("clr_enabled", user: 'USER', password: 'PASSWORD') do
14
+ its("value_in_use") { should cmp "0" }
15
+ its("value_configured") { should cmp "0" }
16
+ end
17
+ EXAMPLE
18
+
19
+ attr_reader :mssql_session, :sql_query
20
+
21
+ def initialize(conf_param_name, opts = {})
22
+ opts[:username] ||= "SA"
23
+ @mssql_session = inspec.mssql_session(opts)
24
+ setting = conf_param_name.to_s.gsub("_", " ").split.map(&:capitalize).join(" ")
25
+ determine_system_configurations(setting)
26
+ end
27
+
28
+ def value_in_use
29
+ sql_query.row(0).column("value_in_use").value
30
+ end
31
+
32
+ def value_configured
33
+ sql_query.row(0).column("value_configured").value
34
+ end
35
+
36
+ def to_s
37
+ "MsSql DB Configuration"
38
+ end
39
+
40
+ private
41
+
42
+ def determine_system_configurations(setting)
43
+ @sql_query = mssql_session.query("SELECT name, CAST(value as int) as value_configured, CAST(value_in_use as int) as value_in_use FROM sys.configurations WHERE name = '#{setting}'")
44
+ rescue => e
45
+ raise Inspec::Exceptions::ResourceFailed, "Errors fetching database system configurations for Mssql database: #{e}"
46
+ end
47
+ end
48
+ end
@@ -6,12 +6,15 @@ module Inspec::Resources
6
6
  supports platform: "unix"
7
7
  supports platform: "windows"
8
8
 
9
- attr_reader :result
10
9
  def initialize(content)
11
10
  @content = content
12
11
  super({ content: @content })
13
12
  end
14
13
 
14
+ def result
15
+ @content == {} || @content["result"].empty? ? nil : @content
16
+ end
17
+
15
18
  private
16
19
 
17
20
  def parse(content)
@@ -0,0 +1,66 @@
1
+ require "inspec/resources/powershell"
2
+
3
+ module Inspec::Resources
4
+ class Oracle < Inspec.resource(1)
5
+ name "oracle"
6
+ supports platform: "unix"
7
+ supports platform: "windows"
8
+
9
+ desc "The 'oracle' resource is a helper for the 'oracledb_listener_conf'"
10
+
11
+ attr_reader :conf_path
12
+
13
+ def initialize
14
+ case inspec.os[:family]
15
+ when "debian", "redhat", "linux", "suse"
16
+ determine_conf_dir_and_path_in_linux
17
+ when "windows"
18
+ determine_conf_dir_and_path_in_windows
19
+ end
20
+ end
21
+
22
+ def to_s
23
+ "OracleDB"
24
+ end
25
+
26
+ private
27
+
28
+ def determine_conf_dir_and_path_in_linux
29
+ oracle_home = inspec.os_env("ORACLE_HOME").content
30
+
31
+ if oracle_home.nil? || oracle_home.empty?
32
+ warn "$ORACLE_HOME env value not set in the system"
33
+ nil
34
+ else
35
+ conf_path = "#{oracle_home}/network/admin/listener.ora"
36
+ if !inspec.file(conf_path).exist?
37
+ warn "No oracle listener settings found in $ORACLE_HOME/network/admin directory"
38
+ nil
39
+ else
40
+ @conf_path = conf_path
41
+ end
42
+ end
43
+ rescue => e
44
+ fail_resource "Errors reading listener settings: #{e}"
45
+ end
46
+
47
+ def determine_conf_dir_and_path_in_windows
48
+ oracle_home = inspec.os_env("ORACLE_HOME").content
49
+
50
+ if oracle_home.nil? || oracle_home.empty?
51
+ warn "ORACLE_HOME env value not set in the system"
52
+ nil
53
+ else
54
+ conf_path = "#{oracle_home}\\network\\admin\\listener.ora"
55
+ if !inspec.file(conf_path).exist?
56
+ warn "No oracle listener settings found in ORACLE_HOME\\network\\admin directory"
57
+ nil
58
+ else
59
+ @conf_path = conf_path
60
+ end
61
+ end
62
+ rescue => e
63
+ fail_resource "Errors reading listener settings: #{e}"
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,40 @@
1
+ require "inspec/resources/oracledb_session"
2
+
3
+ module Inspec::Resources
4
+ class OracledbConf < Inspec.resource(1)
5
+ name "oracledb_conf"
6
+ supports platform: "unix"
7
+ supports platform: "windows"
8
+ desc "Use the oracledb_conf InSpec audit resource to test the database settings for Oracle DB"
9
+ example <<~EXAMPLE
10
+ describe oracledb_conf(user: 'USER', password: 'PASSWORD') do
11
+ its("audit_sys_operations") { should cmp "true" }
12
+ its("sql92_security") { should cmp "true" }
13
+ end
14
+ EXAMPLE
15
+
16
+ attr_reader :oracledb_session
17
+
18
+ def initialize(opts = {})
19
+ @oracledb_session = inspec.oracledb_session(opts)
20
+ end
21
+
22
+ def method_missing(name)
23
+ setting = name.to_s.upcase
24
+ determine_database_setting(setting)
25
+ end
26
+
27
+ def to_s
28
+ "Oracle DB Configuration"
29
+ end
30
+
31
+ private
32
+
33
+ def determine_database_setting(setting)
34
+ sql_query = oracledb_session.query("SELECT UPPER(VALUE) AS UPPER_VALUE FROM V$SYSTEM_PARAMETER WHERE UPPER(NAME) = '#{setting}'")
35
+ sql_query.row(0).column("UPPER_VALUE").value
36
+ rescue => e
37
+ raise Inspec::Exceptions::ResourceFailed, "Errors fetching database settings for Oracle database: #{e}"
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,123 @@
1
+ require "inspec/utils/object_traversal"
2
+ require "inspec/utils/simpleconfig"
3
+ require "inspec/utils/find_files"
4
+ require "inspec/utils/file_reader"
5
+ require "inspec/resources/oracle"
6
+
7
+ module Inspec::Resources
8
+ class OracledbListenerConf < Inspec.resource(1)
9
+ name "oracledb_listener_conf"
10
+ supports platform: "unix"
11
+ supports platform: "windows"
12
+ desc "Use the oracledb_listener_conf InSpec audit resource to test the listener settings for Oracle DB"
13
+ example <<~EXAMPLE
14
+ describe oracledb_listener_conf do
15
+ its('DEFAULT_SERVICE_LISTENER') { should eq 'XE' }
16
+ end
17
+ EXAMPLE
18
+
19
+ include FindFiles
20
+ include FileReader
21
+ include ObjectTraverser
22
+
23
+ def initialize(conf_path = nil)
24
+ oracle = nil
25
+ if conf_path.nil?
26
+ oracle = inspec.oracle
27
+ @conf_path = oracle.conf_path
28
+ else
29
+ @conf_path = conf_path
30
+ end
31
+
32
+ if oracle && oracle.resource_failed?
33
+ raise oracle.resource_exception_message
34
+ elsif @conf_path.nil?
35
+ return skip_resource "Oracle Listener conf path is not set"
36
+ end
37
+
38
+ @conf_dir = File.expand_path(File.dirname(@conf_path))
39
+ @files_contents = {}
40
+ @content = nil
41
+ @params = nil
42
+ read_content
43
+ end
44
+
45
+ def content
46
+ @content ||= read_content
47
+ end
48
+
49
+ def params(*opts)
50
+ @params || read_content
51
+ res = @params
52
+ opts.each do |opt|
53
+ res = res[opt] unless res.nil?
54
+ end
55
+ res
56
+ end
57
+
58
+ def value(key)
59
+ extract_value(key, @params)
60
+ end
61
+
62
+ def method_missing(*keys)
63
+ keys.shift if keys.is_a?(Array) && keys[0] == :[]
64
+ param = value(keys)
65
+ return nil if param.nil?
66
+ # extract first value if we have only one value in array
67
+ return param[0] if param.length == 1
68
+
69
+ param
70
+ end
71
+
72
+ def to_s
73
+ "Oracle Listener Configuration"
74
+ end
75
+
76
+ private
77
+
78
+ def read_content
79
+ @content = ""
80
+ @params = {}
81
+
82
+ to_read = [@conf_path]
83
+ until to_read.empty?
84
+ base_dir = File.dirname(to_read[0])
85
+ raw_conf = read_file(to_read[0])
86
+ @content += raw_conf
87
+
88
+ opts = {
89
+ assignment_regex: /^\s*([^=]*?)\s*=\s*[']?\s*(.*?)\s*[']?\s*$/,
90
+ }
91
+ params = SimpleConfig.new(raw_conf, opts).params
92
+ @params.merge!(params)
93
+
94
+ to_read = to_read.drop(1)
95
+ # see if there is more config files to include
96
+
97
+ to_read += include_files(params, base_dir).find_all do |fp|
98
+ not @files_contents.key? fp
99
+ end
100
+ end
101
+ @content
102
+ end
103
+
104
+ def include_files(params, base_dir)
105
+ include_files = Array(params["include"]) || []
106
+ include_files += Array(params["include_if_exists"]) || []
107
+ include_files.map! do |f|
108
+ Pathname.new(f).absolute? ? f : File.join(base_dir, f)
109
+ end
110
+
111
+ dirs = Array(params["include_dir"]) || []
112
+ dirs.each do |dir|
113
+ dir = File.join(base_dir, dir) if dir[0] != "/"
114
+ include_files += find_files(dir, depth: 1, type: "file")
115
+ end
116
+ include_files
117
+ end
118
+
119
+ def read_file(path)
120
+ @files_contents[path] ||= read_file_content(path)
121
+ end
122
+ end
123
+ end
@@ -40,11 +40,12 @@ module Inspec::Resources
40
40
  end
41
41
  EXAMPLE
42
42
 
43
- def initialize(user, pass, host = nil, port = nil)
43
+ def initialize(user, pass, host = nil, port = nil, socket_path = nil)
44
44
  @user = user || "postgres"
45
45
  @pass = pass
46
46
  @host = host || "localhost"
47
47
  @port = port || 5432
48
+ @socket_path = socket_path
48
49
  raise Inspec::Exceptions::ResourceFailed, "Can't run PostgreSQL SQL checks without authentication." if @user.nil? || @pass.nil?
49
50
  end
50
51
 
@@ -69,10 +70,20 @@ module Inspec::Resources
69
70
 
70
71
  def create_psql_cmd(query, db = [])
71
72
  dbs = db.map { |x| "#{x}" }.join(" ")
72
- if inspec.os.windows?
73
- "psql -d postgresql://#{@user}:#{@pass}@#{@host}:#{@port}/#{dbs} -A -t -w -c \"#{query}\""
73
+
74
+ if @socket_path && !inspec.os.windows?
75
+ # Socket path and empty host in the connection string establishes socket connection
76
+ # Socket connection only enabled for non-windows platforms
77
+ # Windows does not support unix domain sockets
78
+ "psql -d postgresql://#{@user}:#{@pass}@/#{dbs}?host=#{@socket_path} -A -t -w -c #{escaped_query(query)}"
74
79
  else
75
- "psql -d postgresql://#{@user}:#{@pass}@#{@host}:#{@port}/#{dbs} -A -t -w -c #{escaped_query(query)}"
80
+ # Host in connection string establishes tcp/ip connection
81
+ if inspec.os.windows?
82
+ warn "Socket based connection not supported in windows, connecting using host" if @socket_path
83
+ "psql -d postgresql://#{@user}:#{@pass}@#{@host}:#{@port}/#{dbs} -A -t -w -c \"#{query}\""
84
+ else
85
+ "psql -d postgresql://#{@user}:#{@pass}@#{@host}:#{@port}/#{dbs} -A -t -w -c #{escaped_query(query)}"
86
+ end
76
87
  end
77
88
  end
78
89
  end
@@ -141,7 +141,7 @@ module Inspec::Resources
141
141
  elsif version > 0
142
142
  SysV.new(inspec, service_ctl || "/usr/sbin/service")
143
143
  end
144
- when "redhat", "fedora", "centos", "oracle", "cloudlinux", "scientific"
144
+ when "redhat", "fedora", "centos", "oracle", "cloudlinux", "scientific", "rocky", "almalinux"
145
145
  version = os[:release].to_i
146
146
 
147
147
  systemd = ((platform != "fedora" && version >= 7) ||
@@ -0,0 +1,37 @@
1
+ require "inspec/resources/sybase_session"
2
+
3
+ module Inspec::Resources
4
+ class SybaseConf < Inspec.resource(1)
5
+ name "sybase_conf"
6
+ supports platform: "unix"
7
+ # supports platform: "windows" # TODO
8
+ desc "Use the sybase_conf InSpec resource to test Sybase config settings"
9
+ example <<~EXAMPLE
10
+ describe sybase_conf("max memory", password: 'password', server: 'SYBASE') do
11
+ its("run_value") { should cmp 180224 }
12
+ end
13
+ EXAMPLE
14
+
15
+ attr_reader :conf_param, :sql_query
16
+ def initialize(conf_param_name, opts = {})
17
+ @conf_param = conf_param_name
18
+ opts[:username] ||= "sa"
19
+ opts[:database] ||= "master"
20
+ sql_session = inspec.sybase_session(opts)
21
+ @sql_query = sql_session.query("sp_configure \"#{conf_param}\"")
22
+ end
23
+
24
+ def run_value
25
+ sql_query.row(0).column("Run Value").value
26
+ end
27
+
28
+ def config_value
29
+ sql_query.row(0).column("Config Value").value
30
+ end
31
+
32
+ def to_s
33
+ "Sybase Conf #{conf_param}"
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,111 @@
1
+ require "inspec/resources/command"
2
+ require "inspec/utils/database_helpers"
3
+ require "hashie/mash"
4
+ require "csv" unless defined?(CSV)
5
+ require "tempfile" unless defined?(Tempfile)
6
+
7
+ module Inspec::Resources
8
+ # STABILITY: Experimental
9
+ # This resource needs further testing and refinement
10
+ #
11
+ class SybaseSession < Inspec.resource(1)
12
+ name "sybase_session"
13
+ supports platform: "unix"
14
+ # supports platform: "windows" # TODO
15
+ desc "Use the sybase_session InSpec resource to test commands against an Sybase database"
16
+ example <<~EXAMPLE
17
+ sql = sybase_session(username: 'my_user', password: 'password', server: 'SYBASE', database: 'pubs2')
18
+ describe sql.query(\"SELECT * FROM authors\").row(0).column('au_lname') do
19
+ its('value') { should eq 'Smith' }
20
+ end
21
+ EXAMPLE
22
+
23
+ # TODO: allow to set -I interfaces file
24
+ # TODO: allow to customize -s column separator
25
+ attr_reader :bin, :col_sep, :database, :password, :server, :sybase_home, :username
26
+
27
+ def initialize(opts = {})
28
+ @username = opts[:username]
29
+ @password = opts[:password]
30
+ @database = opts[:database]
31
+ @server = opts[:server]
32
+ @sybase_home = opts[:sybase_home] || "/opt/sap"
33
+ @bin = opts[:bin] || "isql"
34
+ @col_sep = "|"
35
+
36
+ fail_resource "Can't run Sybase checks without authentication" unless username && password
37
+ fail_resource "You must provide a server name for the session" unless server
38
+ fail_resource "You must provide a database name for the session" unless database
39
+ fail_resource "Cannot find #{bin} CLI tool" unless inspec.command(bin).exist?
40
+ end
41
+
42
+ def query(sql)
43
+ # We must write the SQl to a temp file on the remote target
44
+ # try to get a temp path
45
+ sql_file_path = upload_sql_file(sql)
46
+
47
+ # isql reuires that we have a matching locale set, but does not support C.UTF-8. en_US.UTF-8 is the least evil.
48
+ command = "LANG=en_US.UTF-8 SYBASE=#{sybase_home} #{bin} -s\"#{col_sep}\" -w80000 -S #{server} -U #{username} -D #{database} -P \"#{password}\" < #{sql_file_path}"
49
+ isql_cmd = inspec.command(command)
50
+
51
+ # Check for isql errors
52
+ res = isql_cmd.exit_status
53
+ raise Inspec::Exceptions::ResourceFailed.new("isql exited with code #{res} and stderr '#{isql_cmd.stderr}', stdout '#{isql_cmd.stdout}'") unless res == 0
54
+ # isql is ill-behaved, and returns 0 on error
55
+ raise Inspec::Exceptions::ResourceFailed.new("isql exited with error '#{isql_cmd.stderr}', stdout '#{isql_cmd.stdout}'") unless isql_cmd.stderr == ""
56
+ # check stdout for error messages when stderr is empty "Msg 102, Level 15, State 181:\nServer 'SYBASE', Line 1:\nIncorrect syntax near '.'.\n"
57
+ raise Inspec::Exceptions::ResourceFailed.new("isql exited with error #{isql_cmd.stdout}") if isql_cmd.stdout.match?(/Msg\s\d+,\sLevel\s\d+,\sState\s\d+/)
58
+
59
+ # Clean up temporary file
60
+ rm_cmd = inspec.command("rm #{sql_file_path}")
61
+ res = rm_cmd.exit_status # TODO: handle
62
+ raise Inspec::Exceptions::ResourceFailed.new("Unable to delete temproary SQL input file at #{sql_file_path}: #{rm_cmd.stderr}") unless res == 0
63
+
64
+ DatabaseHelper::SQLQueryResult.new(isql_cmd, parse_csv_result(isql_cmd.stdout))
65
+ end
66
+
67
+ def to_s
68
+ "Sybase Session"
69
+ end
70
+
71
+ private
72
+
73
+ def parse_csv_result(stdout)
74
+ output = stdout.gsub(/\r/, "").strip
75
+ lines = output.lines
76
+ # Remove second row (all dashes) and last 2 rows (blank and summary lines)
77
+ trimmed_output = ([lines[0]] << lines.slice(2..-3)).join("")
78
+ header_converter = Proc.new do |header|
79
+ # This is here to suppress a warning from Hashie::Mash when it encounters a
80
+ # header column that ends up with the name "default", which happens when using the
81
+ # sybase_conf resource. It does mean that aly query whose output field includes the name
82
+ # Default (exactly) will get renamed to default_value, but that seems unlikely.
83
+ if header.match?(/^Default\s+$/)
84
+ "default_value"
85
+ else
86
+ header.downcase.strip
87
+ end
88
+ end
89
+ field_converter = ->(field) { field&.strip }
90
+ CSV.parse(trimmed_output, headers: true, header_converters: header_converter, converters: field_converter, col_sep: col_sep).map { |row| Hashie::Mash.new(row.to_h) }
91
+ end
92
+
93
+ def upload_sql_file(sql)
94
+ remote_temp_dir = "/tmp"
95
+ remote_file_path = nil
96
+ local_temp_file = Tempfile.new(["sybase", ".sql"])
97
+ begin
98
+ local_temp_file.write("#{sql}\n")
99
+ local_temp_file.write("go\n")
100
+ local_temp_file.flush
101
+ filename = File.basename(local_temp_file.path)
102
+ remote_file_path = "#{remote_temp_dir}/#{filename}"
103
+ inspec.backend.upload([local_temp_file.path], remote_temp_dir)
104
+ ensure
105
+ local_temp_file.close
106
+ local_temp_file.unlink
107
+ end
108
+ remote_file_path
109
+ end
110
+ end
111
+ end
@@ -58,6 +58,8 @@ require "inspec/resources/groups"
58
58
  require "inspec/resources/grub_conf"
59
59
  require "inspec/resources/host"
60
60
  require "inspec/resources/http"
61
+ require "inspec/resources/ibmdb2_conf"
62
+ require "inspec/resources/ibmdb2_session"
61
63
  require "inspec/resources/iis_app"
62
64
  require "inspec/resources/iis_app_pool"
63
65
  require "inspec/resources/iis_site"
@@ -76,6 +78,7 @@ require "inspec/resources/mongodb_conf"
76
78
  require "inspec/resources/mongodb_session"
77
79
  require "inspec/resources/mount"
78
80
  require "inspec/resources/mssql_session"
81
+ require "inspec/resources/mssql_sys_conf"
79
82
  require "inspec/resources/mysql"
80
83
  require "inspec/resources/mysql_conf"
81
84
  require "inspec/resources/mysql_session"
@@ -84,6 +87,9 @@ require "inspec/resources/nginx_conf"
84
87
  require "inspec/resources/npm"
85
88
  require "inspec/resources/ntp_conf"
86
89
  require "inspec/resources/oneget"
90
+ require "inspec/resources/oracle"
91
+ require "inspec/resources/oracledb_conf"
92
+ require "inspec/resources/oracledb_listener_conf"
87
93
  require "inspec/resources/opa_cli"
88
94
  require "inspec/resources/opa_api"
89
95
  require "inspec/resources/oracledb_session"
@@ -49,7 +49,6 @@ module Inspec
49
49
  end
50
50
 
51
51
  class Profile
52
- # Good candidate for keyword_init, but that is not in 2.4
53
52
  Dependency = Struct.new(
54
53
  :name, :path, :status, :status_message, :git, :url, :compliance, :supermarket, :branch, :tag, :commit, :version, :relative_path
55
54
  ) do
@@ -71,7 +70,6 @@ module Inspec
71
70
  end
72
71
  end
73
72
 
74
- # Good candidate for keyword_init, but that is not in 2.4
75
73
  Group = Struct.new(
76
74
  :title, :controls, :id
77
75
  ) do
@@ -1,3 +1,3 @@
1
1
  module Inspec
2
- VERSION = "4.41.20".freeze
2
+ VERSION = "4.46.13".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.41.20
4
+ version: 4.46.13
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-09-01 00:00:00.000000000 Z
11
+ date: 2021-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef-telemetry
@@ -506,6 +506,7 @@ files:
506
506
  - lib/inspec/resources/bridge.rb
507
507
  - lib/inspec/resources/bsd_service.rb
508
508
  - lib/inspec/resources/chocolatey_package.rb
509
+ - lib/inspec/resources/chrony_conf.rb
509
510
  - lib/inspec/resources/command.rb
510
511
  - lib/inspec/resources/cpan.rb
511
512
  - lib/inspec/resources/cran.rb
@@ -535,6 +536,8 @@ files:
535
536
  - lib/inspec/resources/grub_conf.rb
536
537
  - lib/inspec/resources/host.rb
537
538
  - lib/inspec/resources/http.rb
539
+ - lib/inspec/resources/ibmdb2_conf.rb
540
+ - lib/inspec/resources/ibmdb2_session.rb
538
541
  - lib/inspec/resources/iis_app.rb
539
542
  - lib/inspec/resources/iis_app_pool.rb
540
543
  - lib/inspec/resources/iis_site.rb
@@ -559,6 +562,7 @@ files:
559
562
  - lib/inspec/resources/mongodb_session.rb
560
563
  - lib/inspec/resources/mount.rb
561
564
  - lib/inspec/resources/mssql_session.rb
565
+ - lib/inspec/resources/mssql_sys_conf.rb
562
566
  - lib/inspec/resources/mysql.rb
563
567
  - lib/inspec/resources/mysql_conf.rb
564
568
  - lib/inspec/resources/mysql_session.rb
@@ -571,6 +575,9 @@ files:
571
575
  - lib/inspec/resources/opa.rb
572
576
  - lib/inspec/resources/opa_api.rb
573
577
  - lib/inspec/resources/opa_cli.rb
578
+ - lib/inspec/resources/oracle.rb
579
+ - lib/inspec/resources/oracledb_conf.rb
580
+ - lib/inspec/resources/oracledb_listener_conf.rb
574
581
  - lib/inspec/resources/oracledb_session.rb
575
582
  - lib/inspec/resources/os.rb
576
583
  - lib/inspec/resources/os_env.rb
@@ -604,6 +611,8 @@ files:
604
611
  - lib/inspec/resources/ssh_config.rb
605
612
  - lib/inspec/resources/sshd_config.rb
606
613
  - lib/inspec/resources/ssl.rb
614
+ - lib/inspec/resources/sybase_conf.rb
615
+ - lib/inspec/resources/sybase_session.rb
607
616
  - lib/inspec/resources/sys_info.rb
608
617
  - lib/inspec/resources/systemd_service.rb
609
618
  - lib/inspec/resources/sysv_service.rb