inspec-core 4.38.9 → 4.49.0

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -1
  3. data/etc/deprecations.json +1 -1
  4. data/lib/inspec/base_cli.rb +11 -1
  5. data/lib/inspec/cached_fetcher.rb +2 -2
  6. data/lib/inspec/cli.rb +14 -4
  7. data/lib/inspec/control_eval_context.rb +64 -17
  8. data/lib/inspec/dsl.rb +18 -3
  9. data/lib/inspec/fetcher/url.rb +45 -3
  10. data/lib/inspec/fetcher.rb +3 -3
  11. data/lib/inspec/plugin/v1/registry.rb +6 -2
  12. data/lib/inspec/profile.rb +146 -6
  13. data/lib/inspec/resources/apache_conf.rb +8 -6
  14. data/lib/inspec/resources/cassandra.rb +64 -0
  15. data/lib/inspec/resources/cassandradb_conf.rb +47 -0
  16. data/lib/inspec/resources/cassandradb_session.rb +68 -0
  17. data/lib/inspec/resources/chrony_conf.rb +55 -0
  18. data/lib/inspec/resources/csv.rb +26 -3
  19. data/lib/inspec/resources/groups.rb +22 -3
  20. data/lib/inspec/resources/ibmdb2_conf.rb +57 -0
  21. data/lib/inspec/resources/ibmdb2_session.rb +69 -0
  22. data/lib/inspec/resources/mongodb_session.rb +88 -0
  23. data/lib/inspec/resources/mssql_sys_conf.rb +48 -0
  24. data/lib/inspec/resources/opa.rb +26 -0
  25. data/lib/inspec/resources/opa_api.rb +39 -0
  26. data/lib/inspec/resources/opa_cli.rb +43 -0
  27. data/lib/inspec/resources/oracle.rb +66 -0
  28. data/lib/inspec/resources/oracledb_conf.rb +40 -0
  29. data/lib/inspec/resources/oracledb_listener_conf.rb +123 -0
  30. data/lib/inspec/resources/oracledb_session.rb +23 -6
  31. data/lib/inspec/resources/postgres_session.rb +15 -10
  32. data/lib/inspec/resources/registry_key.rb +1 -1
  33. data/lib/inspec/resources/security_identifier.rb +8 -14
  34. data/lib/inspec/resources/security_policy.rb +4 -3
  35. data/lib/inspec/resources/service.rb +7 -1
  36. data/lib/inspec/resources/sybase_conf.rb +37 -0
  37. data/lib/inspec/resources/sybase_session.rb +111 -0
  38. data/lib/inspec/resources/users.rb +16 -2
  39. data/lib/inspec/resources/windows_firewall.rb +1 -1
  40. data/lib/inspec/resources/wmi.rb +1 -1
  41. data/lib/inspec/resources.rb +12 -0
  42. data/lib/inspec/run_data/profile.rb +0 -2
  43. data/lib/inspec/runner.rb +2 -0
  44. data/lib/inspec/utils/filter.rb +1 -1
  45. data/lib/inspec/version.rb +1 -1
  46. data/lib/plugins/inspec-init/templates/profiles/aws/inspec.yml +1 -1
  47. data/lib/plugins/inspec-init/templates/profiles/azure/inspec.yml +1 -1
  48. data/lib/plugins/inspec-init/templates/profiles/gcp/inspec.yml +1 -1
  49. data/lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli/cli_command.rb +16 -15
  50. metadata +18 -2
@@ -0,0 +1,64 @@
1
+ module Inspec::Resources
2
+ class Cassandra < Inspec.resource(1)
3
+ name "cassandra"
4
+ supports platform: "unix"
5
+ supports platform: "windows"
6
+
7
+ desc "The 'cassandra' resource is a helper for the 'cql_conf'"
8
+
9
+ attr_reader :conf_path
10
+
11
+ def initialize
12
+ case inspec.os[:family]
13
+ when "debian", "redhat", "linux", "suse"
14
+ determine_conf_dir_and_path_in_linux
15
+ when "windows"
16
+ determine_conf_dir_and_path_in_windows
17
+ end
18
+ end
19
+
20
+ def to_s
21
+ "CassandraDB"
22
+ end
23
+
24
+ private
25
+
26
+ def determine_conf_dir_and_path_in_linux
27
+ cassandra_home = inspec.os_env("CASSANDRA_HOME").content
28
+
29
+ if cassandra_home.nil? || cassandra_home.empty?
30
+ warn "$CASSANDRA_HOME environment variable not set in the system"
31
+ nil
32
+ else
33
+ conf_path = "#{cassandra_home}/cassandra.yaml"
34
+ if !inspec.file(conf_path).exist?
35
+ warn "Cassandra conf file not found in #{cassandra_home} directory."
36
+ nil
37
+ else
38
+ @conf_path = conf_path
39
+ end
40
+ end
41
+ rescue => e
42
+ fail_resource "Errors reading cassandra conf file: #{e}"
43
+ end
44
+
45
+ def determine_conf_dir_and_path_in_windows
46
+ cassandra_home = inspec.os_env("CASSANDRA_HOME").content
47
+
48
+ if cassandra_home.nil? || cassandra_home.empty?
49
+ warn "CASSANDRA_HOME environment variable not set in the system"
50
+ nil
51
+ else
52
+ conf_path = "#{cassandra_home}\\conf\\cassandra.yaml"
53
+ if !inspec.file(conf_path).exist?
54
+ warn "Cassandra conf file not found in #{cassandra_home}\\conf directory."
55
+ nil
56
+ else
57
+ @conf_path = conf_path
58
+ end
59
+ end
60
+ rescue => e
61
+ fail_resource "Errors reading cassandra conf file: #{e}"
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,47 @@
1
+ require "inspec/resources/json"
2
+ require "inspec/resources/cassandra"
3
+
4
+ module Inspec::Resources
5
+ class CassandradbConf < JsonConfig
6
+ name "cassandradb_conf"
7
+ supports platform: "unix"
8
+ supports platform: "windows"
9
+ desc "Use the cql_conf InSpec audit resource to test the contents of the configuration file for Cassandra DB"
10
+ example <<~EXAMPLE
11
+ describe cassandradb_conf do
12
+ its('listen_address') { should eq '0.0.0.0' }
13
+ end
14
+ EXAMPLE
15
+
16
+ def initialize(conf_path = nil)
17
+ cassandra = nil
18
+ if conf_path.nil?
19
+ cassandra = inspec.cassandra
20
+ @conf_path = cassandra.conf_path
21
+ else
22
+ @conf_path = conf_path
23
+ end
24
+
25
+ if cassandra && cassandra.resource_failed?
26
+ raise cassandra.resource_exception_message
27
+ elsif @conf_path.nil?
28
+ return skip_resource "Cassandra db conf path is not set"
29
+ end
30
+
31
+ super(@conf_path)
32
+ end
33
+
34
+ private
35
+
36
+ def parse(content)
37
+ YAML.load(content)
38
+ rescue => e
39
+ raise Inspec::Exceptions::ResourceFailed, "Unable to parse `cassandra.yaml` file: #{e.message}"
40
+ end
41
+
42
+ def resource_base_name
43
+ "Cassandra Configuration"
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,68 @@
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 CassandradbSession < Inspec.resource(1)
16
+ name "cassandradb_session"
17
+ supports platform: "unix"
18
+ supports platform: "windows"
19
+ desc "Use the cassandradb_session InSpec resource to test commands against an Cassandra database"
20
+ example <<~EXAMPLE
21
+ cql = cassandradb_session(user: 'my_user', password: 'password', host: 'host', port: 'port')
22
+ describe cql.query("SELECT cluster_name FROM system.local") do
23
+ its('output') { should match /Test Cluster/ }
24
+ end
25
+ EXAMPLE
26
+
27
+ attr_reader :user, :password, :host, :port
28
+
29
+ def initialize(opts = {})
30
+ @user = opts[:user] || "cassandra"
31
+ @password = opts[:password] || "cassandra"
32
+ @host = opts[:host]
33
+ @port = opts[:port]
34
+ end
35
+
36
+ def query(q)
37
+ cassandra_cmd = create_cassandra_cmd(q)
38
+ cmd = inspec.command(cassandra_cmd)
39
+ out = cmd.stdout + "\n" + cmd.stderr
40
+ if cmd.exit_status != 0 || out =~ /Unable to connect to any servers/ || out.downcase =~ /^error:.*/
41
+ raise Inspec::Exceptions::ResourceFailed, "Cassandra query with errors: #{out}"
42
+ else
43
+ Lines.new(cmd.stdout.strip, "Cassandra query: #{q}")
44
+ end
45
+ end
46
+
47
+ def to_s
48
+ "Cassandra DB Session"
49
+ end
50
+
51
+ private
52
+
53
+ def create_cassandra_cmd(q)
54
+ # TODO: simple escape, must be handled by a library
55
+ # that does this securely
56
+ escaped_query = q.gsub(/\\/, "\\\\").gsub(/"/, '\\"').gsub(/\$/, '\\$')
57
+
58
+ # construct the query
59
+ command = "cqlsh"
60
+ command += " #{@host}" unless @host.nil?
61
+ command += " #{@port}" unless @port.nil?
62
+ command += " -u #{@user}"
63
+ command += " -p #{@password}"
64
+ command += " --execute '#{escaped_query}'"
65
+ command
66
+ end
67
+ end
68
+ 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
@@ -22,6 +22,18 @@ module Inspec::Resources
22
22
  end
23
23
  end
24
24
 
25
+ # Class defined to check for members without case-sensitivity
26
+ class Members < Array
27
+ def initialize(group_members)
28
+ @group_members = group_members
29
+ super
30
+ end
31
+
32
+ def include?(user)
33
+ !(@group_members.select { |group_member| group_member.casecmp?(user) }.empty?)
34
+ end
35
+ end
36
+
25
37
  class Groups < Inspec.resource(1)
26
38
  include GroupManagementSelector
27
39
 
@@ -82,6 +94,7 @@ module Inspec::Resources
82
94
  # its('gid') { should eq 0 }
83
95
  # end
84
96
  #
97
+
85
98
  class Group < Inspec.resource(1)
86
99
  include GroupManagementSelector
87
100
 
@@ -118,11 +131,13 @@ module Inspec::Resources
118
131
  end
119
132
 
120
133
  def members
121
- flatten_entry(group_info, "members") || empty_value_for_members
134
+ members_list = flatten_entry(group_info, "members") || empty_value_for_members
135
+ inspec.os.windows? ? Members.new(members_list) : members_list
122
136
  end
123
137
 
124
138
  def members_array
125
- flatten_entry(group_info, "members_array") || []
139
+ members_list = flatten_entry(group_info, "members_array") || []
140
+ inspec.os.windows? ? Members.new(members_list) : members_list
126
141
  end
127
142
 
128
143
  def local
@@ -150,7 +165,11 @@ module Inspec::Resources
150
165
  def group_info
151
166
  # we need a local copy for the block
152
167
  group = @group.dup
153
- @groups_cache ||= inspec.groups.where { name == group }
168
+ if inspec.os.windows?
169
+ @groups_cache ||= inspec.groups.where { name.casecmp?(group) }
170
+ else
171
+ @groups_cache ||= inspec.groups.where { name == group }
172
+ end
154
173
  end
155
174
 
156
175
  def empty_value_for_members
@@ -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,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,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
@@ -0,0 +1,26 @@
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
+ def initialize(content)
10
+ @content = content
11
+ super({ content: @content })
12
+ end
13
+
14
+ def result
15
+ @content == {} || @content["result"].empty? ? nil : @content
16
+ end
17
+
18
+ private
19
+
20
+ def parse(content)
21
+ @content = YAML.load(content)
22
+ rescue => e
23
+ raise Inspec::Exceptions::ResourceFailed, "Unable to parse OPA query output: #{e.message}"
24
+ end
25
+ end
26
+ 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