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.
- checksums.yaml +4 -4
- data/Gemfile +5 -1
- data/etc/deprecations.json +1 -1
- data/lib/inspec/base_cli.rb +11 -1
- data/lib/inspec/cached_fetcher.rb +2 -2
- data/lib/inspec/cli.rb +14 -4
- data/lib/inspec/control_eval_context.rb +64 -17
- data/lib/inspec/dsl.rb +18 -3
- data/lib/inspec/fetcher/url.rb +45 -3
- data/lib/inspec/fetcher.rb +3 -3
- data/lib/inspec/plugin/v1/registry.rb +6 -2
- data/lib/inspec/profile.rb +146 -6
- data/lib/inspec/resources/apache_conf.rb +8 -6
- data/lib/inspec/resources/cassandra.rb +64 -0
- data/lib/inspec/resources/cassandradb_conf.rb +47 -0
- data/lib/inspec/resources/cassandradb_session.rb +68 -0
- data/lib/inspec/resources/chrony_conf.rb +55 -0
- data/lib/inspec/resources/csv.rb +26 -3
- data/lib/inspec/resources/groups.rb +22 -3
- data/lib/inspec/resources/ibmdb2_conf.rb +57 -0
- data/lib/inspec/resources/ibmdb2_session.rb +69 -0
- data/lib/inspec/resources/mongodb_session.rb +88 -0
- data/lib/inspec/resources/mssql_sys_conf.rb +48 -0
- data/lib/inspec/resources/opa.rb +26 -0
- data/lib/inspec/resources/opa_api.rb +39 -0
- data/lib/inspec/resources/opa_cli.rb +43 -0
- data/lib/inspec/resources/oracle.rb +66 -0
- data/lib/inspec/resources/oracledb_conf.rb +40 -0
- data/lib/inspec/resources/oracledb_listener_conf.rb +123 -0
- data/lib/inspec/resources/oracledb_session.rb +23 -6
- data/lib/inspec/resources/postgres_session.rb +15 -10
- data/lib/inspec/resources/registry_key.rb +1 -1
- data/lib/inspec/resources/security_identifier.rb +8 -14
- data/lib/inspec/resources/security_policy.rb +4 -3
- data/lib/inspec/resources/service.rb +7 -1
- data/lib/inspec/resources/sybase_conf.rb +37 -0
- data/lib/inspec/resources/sybase_session.rb +111 -0
- data/lib/inspec/resources/users.rb +16 -2
- data/lib/inspec/resources/windows_firewall.rb +1 -1
- data/lib/inspec/resources/wmi.rb +1 -1
- data/lib/inspec/resources.rb +12 -0
- data/lib/inspec/run_data/profile.rb +0 -2
- data/lib/inspec/runner.rb +2 -0
- data/lib/inspec/utils/filter.rb +1 -1
- data/lib/inspec/version.rb +1 -1
- data/lib/plugins/inspec-init/templates/profiles/aws/inspec.yml +1 -1
- data/lib/plugins/inspec-init/templates/profiles/azure/inspec.yml +1 -1
- data/lib/plugins/inspec-init/templates/profiles/gcp/inspec.yml +1 -1
- data/lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli/cli_command.rb +16 -15
- 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
|
data/lib/inspec/resources/csv.rb
CHANGED
@@ -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:
|
45
|
+
csv = CSV.new(content, headers: @headers, converters: %i{all blank_to_nil})
|
32
46
|
|
33
47
|
# convert to hash
|
34
|
-
|
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
|
-
@
|
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
|
-
|
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
|