inspec 1.29.0 → 1.30.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +19 -0
  3. data/bin/inspec +1 -1
  4. data/docs/profiles.md +14 -5
  5. data/docs/resources/iptables.md.erb +12 -5
  6. data/docs/resources/mssql_session.md.erb +11 -28
  7. data/docs/resources/mysql_session.md.erb +12 -0
  8. data/docs/resources/oracledb_session.md.erb +10 -28
  9. data/docs/resources/package.md.erb +6 -0
  10. data/docs/resources/postgres_conf.md.erb +2 -0
  11. data/examples/inheritance/controls/example.rb +0 -1
  12. data/examples/meta-profile/controls/example.rb +0 -1
  13. data/examples/profile/controls/example.rb +0 -1
  14. data/examples/profile/controls/gordon.rb +0 -1
  15. data/inspec.gemspec +1 -0
  16. data/lib/bundles/inspec-compliance/api.rb +12 -10
  17. data/lib/bundles/inspec-init/templates/profile/controls/example.rb +0 -1
  18. data/lib/inspec.rb +0 -1
  19. data/lib/inspec/backend.rb +0 -1
  20. data/lib/inspec/cli.rb +1 -1
  21. data/lib/inspec/metadata.rb +1 -1
  22. data/lib/inspec/polyfill.rb +0 -1
  23. data/lib/inspec/profile.rb +1 -1
  24. data/lib/inspec/resource.rb +1 -1
  25. data/lib/inspec/rule.rb +0 -1
  26. data/lib/inspec/runner.rb +0 -1
  27. data/lib/inspec/version.rb +1 -1
  28. data/lib/matchers/matchers.rb +0 -1
  29. data/lib/resources/apache.rb +0 -1
  30. data/lib/resources/apache_conf.rb +0 -1
  31. data/lib/resources/audit_policy.rb +0 -1
  32. data/lib/resources/auditd_conf.rb +0 -1
  33. data/lib/resources/auditd_rules.rb +0 -1
  34. data/lib/resources/command.rb +0 -1
  35. data/lib/resources/directory.rb +7 -3
  36. data/lib/resources/docker.rb +30 -3
  37. data/lib/resources/etc_group.rb +0 -1
  38. data/lib/resources/file.rb +0 -1
  39. data/lib/resources/grub_conf.rb +0 -1
  40. data/lib/resources/inetd_conf.rb +0 -1
  41. data/lib/resources/kernel_module.rb +0 -1
  42. data/lib/resources/kernel_parameter.rb +0 -1
  43. data/lib/resources/limits_conf.rb +0 -1
  44. data/lib/resources/login_def.rb +0 -1
  45. data/lib/resources/mssql_session.rb +62 -14
  46. data/lib/resources/mysql.rb +0 -1
  47. data/lib/resources/mysql_conf.rb +0 -1
  48. data/lib/resources/mysql_session.rb +15 -6
  49. data/lib/resources/nginx_conf.rb +95 -0
  50. data/lib/resources/ntp_conf.rb +0 -1
  51. data/lib/resources/oracledb_session.rb +109 -12
  52. data/lib/resources/os_env.rb +0 -1
  53. data/lib/resources/package.rb +47 -3
  54. data/lib/resources/packages.rb +0 -1
  55. data/lib/resources/parse_config.rb +0 -1
  56. data/lib/resources/passwd.rb +0 -1
  57. data/lib/resources/postgres.rb +9 -5
  58. data/lib/resources/postgres_conf.rb +12 -3
  59. data/lib/resources/postgres_session.rb +0 -1
  60. data/lib/resources/powershell.rb +0 -1
  61. data/lib/resources/processes.rb +0 -1
  62. data/lib/resources/registry_key.rb +0 -1
  63. data/lib/resources/service.rb +1 -1
  64. data/lib/resources/ssh_conf.rb +0 -1
  65. data/lib/resources/ssl.rb +0 -1
  66. data/lib/utils/database_helpers.rb +77 -0
  67. data/lib/utils/filter_array.rb +0 -1
  68. data/lib/utils/find_files.rb +0 -1
  69. data/lib/utils/nginx_parser.rb +4 -2
  70. data/lib/utils/simpleconfig.rb +0 -1
  71. metadata +18 -2
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
- # Copyright 2015 Dominik Richter. All rights reserved.
2
+ # Copyright 2015 Dominik Richter
3
3
  # author: Dominik Richter
4
4
  # author: Christoph Hartmann
5
5
 
@@ -1,6 +1,5 @@
1
1
  # encoding: utf-8
2
2
  # copyright: 2015, Vulcano Security GmbH
3
- # license: All rights reserved
4
3
  # author: Dominik Richter
5
4
  # author: Christoph Hartmann
6
5
  require 'inspec/plugins'
@@ -112,6 +111,7 @@ require 'resources/mssql_session'
112
111
  require 'resources/mysql'
113
112
  require 'resources/mysql_conf'
114
113
  require 'resources/mysql_session'
114
+ require 'resources/nginx_conf'
115
115
  require 'resources/npm'
116
116
  require 'resources/ntp_conf'
117
117
  require 'resources/oneget'
data/lib/inspec/rule.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  # encoding: utf-8
2
2
  # copyright: 2015, Dominik Richter
3
- # license: All rights reserved
4
3
  # author: Dominik Richter
5
4
  # author: Christoph Hartmann
6
5
 
data/lib/inspec/runner.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  # encoding: utf-8
2
2
  # copyright: 2015, Dominik Richter
3
- # license: All rights reserved
4
3
  # author: Dominik Richter
5
4
  # author: Christoph Hartmann
6
5
 
@@ -4,5 +4,5 @@
4
4
  # author: Christoph Hartmann
5
5
 
6
6
  module Inspec
7
- VERSION = '1.29.0'.freeze
7
+ VERSION = '1.30.0'.freeze
8
8
  end
@@ -2,7 +2,6 @@
2
2
  # copyright: 2015, Vulcano Security GmbH
3
3
  # author: Dominik Richter
4
4
  # author: Christoph Hartmann
5
- # license: All rights reserved
6
5
 
7
6
  RSpec::Matchers.define :be_readable do
8
7
  match do |file|
@@ -2,7 +2,6 @@
2
2
  # copyright: 2015, Vulcano Security GmbH
3
3
  # author: Christoph Hartmann
4
4
  # author: Dominik Richter
5
- # license: All rights reserved
6
5
 
7
6
  module Inspec::Resources
8
7
  class Apache < Inspec.resource(1)
@@ -2,7 +2,6 @@
2
2
  # copyright: 2015, Vulcano Security GmbH
3
3
  # author: Dominik Richter
4
4
  # author: Christoph Hartmann
5
- # license: All rights reserved
6
5
 
7
6
  require 'utils/simpleconfig'
8
7
  require 'utils/find_files'
@@ -2,7 +2,6 @@
2
2
  # copyright: 2015, Vulcano Security GmbH
3
3
  # author: Christoph Hartmann
4
4
  # author: Dominik Richter
5
- # license: All rights reserved
6
5
 
7
6
  # Advanced Auditing:
8
7
  # As soon as you start applying Advanced Audit Configuration Policy, legacy policies will be completely ignored.
@@ -2,7 +2,6 @@
2
2
  # copyright: 2015, Vulcano Security GmbH
3
3
  # author: Christoph Hartmann
4
4
  # author: Dominik Richter
5
- # license: All rights reserved
6
5
 
7
6
  require 'utils/simpleconfig'
8
7
 
@@ -2,7 +2,6 @@
2
2
  # copyright: 2015, Vulcano Security GmbH
3
3
  # author: Christoph Hartmann
4
4
  # author: Dominik Richter
5
- # license: All rights reserved
6
5
 
7
6
  require 'forwardable'
8
7
  require 'utils/filter_array'
@@ -2,7 +2,6 @@
2
2
  # copyright: 2015, Vulcano Security GmbH
3
3
  # author: Dominik Richter
4
4
  # author: Christoph Hartmann
5
- # license: All rights reserved
6
5
 
7
6
  module Inspec::Resources
8
7
  class Cmd < Inspec.resource(1)
@@ -13,9 +13,13 @@ module Inspec::Resources
13
13
  it { should be_directory }
14
14
  end
15
15
  "
16
- end
17
16
 
18
- def to_s
19
- "Directory #{@path}"
17
+ def exist?
18
+ file.exist? && file.directory?
19
+ end
20
+
21
+ def to_s
22
+ "Directory #{source_path}"
23
+ end
20
24
  end
21
25
  end
@@ -107,7 +107,9 @@ module Inspec::Resources
107
107
 
108
108
  def version
109
109
  return @version if defined?(@version)
110
- data = JSON.parse(inspec.command('docker version --format \'{{ json . }}\'').stdout)
110
+ data = {}
111
+ cmd = inspec.command('docker version --format \'{{ json . }}\'')
112
+ data = JSON.parse(cmd.stdout) if cmd.exit_status == 0
111
113
  @version = Hashie::Mash.new(data)
112
114
  rescue JSON::ParserError => _e
113
115
  return Hashie::Mash.new({})
@@ -115,7 +117,10 @@ module Inspec::Resources
115
117
 
116
118
  def info
117
119
  return @info if defined?(@info)
118
- data = JSON.parse(inspec.command('docker info --format \'{{ json . }}\'').stdout)
120
+ data = {}
121
+ # docke info format is only supported for Docker 17.03+
122
+ cmd = inspec.command('docker info --format \'{{ json . }}\'')
123
+ data = JSON.parse(cmd.stdout) if cmd.exit_status == 0
119
124
  @info = Hashie::Mash.new(data)
120
125
  rescue JSON::ParserError => _e
121
126
  return Hashie::Mash.new({})
@@ -138,7 +143,19 @@ module Inspec::Resources
138
143
  private
139
144
 
140
145
  def parse_containers
141
- raw_containers = inspec.command('docker ps -a --no-trunc --format \'{{ json . }}\'').stdout
146
+ # @see https://github.com/moby/moby/issues/20625, works for docker 1.13+
147
+ # raw_containers = inspec.command('docker ps -a --no-trunc --format \'{{ json . }}\'').stdout
148
+ # therefore we stick with older approach
149
+ labels = %w{Command CreatedAt ID Image Labels Mounts Names Ports RunningFor Size Status}
150
+
151
+ # Networks LocalVolumes work with 1.13+ only
152
+ if !version.empty? && Gem::Version.new(version['Client']['Version']) >= Gem::Version.new('1.13')
153
+ labels.push('Networks')
154
+ labels.push('LocalVolumes')
155
+ end
156
+ # build command
157
+ format = labels.map { |label| "\"#{label}\": {{json .#{label}}}" }
158
+ raw_containers = inspec.command("docker ps -a --no-trunc --format '{#{format.join(', ')}}'").stdout
142
159
  ps = []
143
160
  # since docker is not outputting valid json, we need to parse each row
144
161
  raw_containers.each_line { |entry|
@@ -147,6 +164,9 @@ module Inspec::Resources
147
164
  j = j.map { |k, v|
148
165
  [k.downcase, v]
149
166
  }.to_h
167
+
168
+ # ensure all keys are there
169
+ j = ensure_container_keys(j)
150
170
  ps.push(j)
151
171
  }
152
172
  ps
@@ -155,6 +175,13 @@ module Inspec::Resources
155
175
  []
156
176
  end
157
177
 
178
+ def ensure_container_keys(entry)
179
+ %w{Command CreatedAt ID Image Labels Mounts Names Ports RunningFor Size Status Networks LocalVolumes}.each { |key|
180
+ entry[key.downcase] = nil if !entry.key?(key.downcase)
181
+ }
182
+ entry
183
+ end
184
+
158
185
  def parse_images
159
186
  # docker does not support the `json .` function here, therefore we need to emulate that behavior.
160
187
  raw_images = inspec.command('docker images -a --no-trunc --format \'{ "id": {{json .ID}}, "repository": {{json .Repository}}, "tag": {{json .Tag}}, "size": {{json .Size}}, "digest": {{json .Digest}}, "createdat": {{json .CreatedAt}}, "createdsize": {{json .CreatedSince}} }\'').stdout
@@ -2,7 +2,6 @@
2
2
  # copyright: 2015, Vulcano Security GmbH
3
3
  # author: Christoph Hartmann
4
4
  # author: Dominik Richter
5
- # license: All rights reserved
6
5
 
7
6
  # The file format consists of
8
7
  # - group name
@@ -2,7 +2,6 @@
2
2
  # copyright: 2015, Vulcano Security GmbH
3
3
  # author: Dominik Richter
4
4
  # author: Christoph Hartmann
5
- # license: All rights reserved
6
5
 
7
6
  require 'shellwords'
8
7
 
@@ -1,6 +1,5 @@
1
1
  # encoding: utf-8
2
2
  # author: Thomas Cate
3
- # license: All rights reserved
4
3
 
5
4
  require 'utils/simpleconfig'
6
5
 
@@ -2,7 +2,6 @@
2
2
  # copyright: 2015, Vulcano Security GmbH
3
3
  # author: Christoph Hartmann
4
4
  # author: Dominik Richter
5
- # license: All rights reserved
6
5
 
7
6
  require 'utils/simpleconfig'
8
7
 
@@ -1,7 +1,6 @@
1
1
  # encoding: utf-8
2
2
  # author: Christoph Hartmann
3
3
  # author: Dominik Richter
4
- # license: All rights reserved
5
4
 
6
5
  module Inspec::Resources
7
6
  class KernelModule < Inspec.resource(1)
@@ -1,6 +1,5 @@
1
1
  # encoding: utf-8
2
2
  # author: Christoph Hartmann
3
- # license: All rights reserved
4
3
 
5
4
  module Inspec::Resources
6
5
  class KernelParameter < Inspec.resource(1)
@@ -2,7 +2,6 @@
2
2
  # copyright: 2015, Vulcano Security GmbH
3
3
  # author: Christoph Hartmann
4
4
  # author: Dominik Richter
5
- # license: All rights reserved
6
5
 
7
6
  require 'utils/simpleconfig'
8
7
 
@@ -2,7 +2,6 @@
2
2
  # copyright: 2015, Vulcano Security GmbH
3
3
  # author: Christoph Hartmann
4
4
  # author: Dominik Richter
5
- # license: All rights reserved
6
5
 
7
6
  require 'utils/simpleconfig'
8
7
 
@@ -1,54 +1,102 @@
1
1
  # encoding: utf-8
2
+ # author: Nolan Davidson
2
3
  # author: Christoph Hartmann
3
4
  # author: Dominik Richter
4
5
 
6
+ require 'hashie/mash'
7
+ require 'utils/database_helpers'
8
+
5
9
  module Inspec::Resources
10
+ # STABILITY: Experimental
11
+ # This resource needs further testing and refinement
12
+ #
13
+ # This requires the `sqlcmd` tool available on platform
14
+ # @see https://docs.microsoft.com/en-us/sql/relational-databases/scripting/sqlcmd-use-the-utility
15
+ # @see https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-connect-and-query-sqlcmd
6
16
  class MssqlSession < Inspec.resource(1)
7
17
  name 'mssql_session'
8
18
  desc 'Use the mssql_session InSpec audit resource to test SQL commands run against a MS Sql Server database.'
9
19
  example "
10
20
  # Using SQL authentication
11
21
  sql = mssql_session(user: 'myuser', pass: 'mypassword')
12
- describe sql.query('select * from sys.databases where name like \'*test*\') do
13
- its('stdout') { should_not match(/test/) }
22
+ describe sql.query('SELECT * FROM table').row(0).column('columnname') do
23
+ its('value') { should cmp == 1 }
14
24
  end
15
25
 
16
26
  # Passing no credentials to mssql_session forces it to use Windows authentication
17
27
  sql_windows_auth = mssql_session
18
- describe sql_window_auth.query('select * from sys.databases where name like \'*test*\') do
19
- its('stdout') { should_not match(/test/) }
28
+ describe sql.query(\"SELECT SERVERPROPERTY('IsIntegratedSecurityOnly') as \\\"login_mode\\\";\").row(0).column('login_mode') do
29
+ its('value') { should_not be_empty }
30
+ its('value') { should cmp == 1 }
20
31
  end
21
32
  "
22
33
 
23
- attr_reader :user, :pass, :host
24
-
34
+ attr_reader :user, :password, :host
25
35
  def initialize(opts = {})
26
36
  @user = opts[:user]
27
- @pass = opts[:pass]
37
+ @password = opts[:password] || opts[:pass]
38
+ if opts[:pass]
39
+ warn '[DEPRECATED] use `password` option to supply password instead of `pass`'
40
+ end
28
41
  @host = opts[:host] || 'localhost'
29
42
  @instance = opts[:instance]
43
+
44
+ # check if sqlcmd is available
45
+ return skip_resource('sqlcmd is missing') if !inspec.command('sqlcmd').exist?
46
+ # check that database is reachable
47
+ return skip_resource("Can't connect to the MS SQL Server.") if !test_connection
30
48
  end
31
49
 
32
50
  def query(q)
33
- escaped_query = q.gsub(/\\/, '\\\\').gsub(/"/, '\\"').gsub(/\$/, '\\$').gsub(/\@/, '`@')
34
- cmd_string = "sqlcmd -Q \"#{escaped_query}\""
35
- cmd_string += " -U #{@user} -P #{@pass}" unless @user.nil? or @pass.nil?
51
+ escaped_query = q.gsub(/\\/, '\\\\').gsub(/"/, '\\"').gsub(/\$/, '\\$')
52
+ # surpress 'x rows affected' in SQLCMD with 'set nocount on;'
53
+ cmd_string = "sqlcmd -Q \"set nocount on; #{escaped_query}\" -W -w 1024 -s ','"
54
+ cmd_string += " -U #{@user} -P '#{@password}'" unless @user.nil? || @password.nil?
36
55
  if @instance.nil?
37
56
  cmd_string += " -S #{@host}"
38
57
  else
39
58
  cmd_string += " -S #{@host}\\#{@instance}"
40
59
  end
41
- puts cmd_string
42
60
  cmd = inspec.command(cmd_string)
43
61
  out = cmd.stdout + "\n" + cmd.stderr
44
- if out =~ /Sqlcmd: Error/
45
- skip_resource("Can't connect to the MS SQL Server.")
62
+ if cmd.exit_status != 0 || out =~ /Sqlcmd: Error/
63
+ # TODO: we need to throw an exception here
64
+ # change once https://github.com/chef/inspec/issues/1205 is in
65
+ warn "Could not execute the sql query #{out}"
66
+ DatabaseHelper::SQLQueryResult.new(cmd, Hashie::Mash.new({}))
67
+ else
68
+ DatabaseHelper::SQLQueryResult.new(cmd, parse_csv_result(cmd))
46
69
  end
47
- cmd
48
70
  end
49
71
 
50
72
  def to_s
51
73
  'MSSQL session'
52
74
  end
75
+
76
+ private
77
+
78
+ def test_connection
79
+ !query('select getdate()').empty?
80
+ end
81
+
82
+ def parse_csv_result(cmd)
83
+ require 'csv'
84
+ table = CSV.parse(cmd.stdout, { headers: true })
85
+
86
+ # remove first row, since it will be a seperator line
87
+ table.delete(0)
88
+
89
+ # convert to hash
90
+ headers = table.headers
91
+
92
+ results = table.map { |row|
93
+ res = {}
94
+ headers.each { |header|
95
+ res[header.downcase] = row[header]
96
+ }
97
+ Hashie::Mash.new(res)
98
+ }
99
+ results
100
+ end
53
101
  end
54
102
  end
@@ -2,7 +2,6 @@
2
2
  # copyright: 2015, Vulcano Security GmbH
3
3
  # author: Dominik Richter
4
4
  # author: Christoph Hartmann
5
- # license: All rights reserved
6
5
 
7
6
  module Inspec::Resources
8
7
  class Mysql < Inspec.resource(1)
@@ -1,7 +1,6 @@
1
1
  # encoding: utf-8
2
2
  # copyright: 2015, Vulcano Security GmbH
3
3
  # author: Dominik Richter
4
- # license: All rights reserved
5
4
 
6
5
  require 'utils/simpleconfig'
7
6
  require 'utils/find_files'
@@ -3,7 +3,6 @@
3
3
  # author: Dominik Richter
4
4
  # author: Christoph Hartmann
5
5
  # author: Aaron Lippold
6
- # license: All rights reserved
7
6
 
8
7
  module Inspec::Resources
9
8
  class MysqlSession < Inspec.resource(1)
@@ -16,10 +15,12 @@ module Inspec::Resources
16
15
  end
17
16
  "
18
17
 
19
- def initialize(user = nil, pass = nil, host = 'localhost')
18
+ def initialize(user = nil, pass = nil, host = 'localhost', port = nil, socket = nil)
20
19
  @user = user
21
20
  @pass = pass
22
21
  @host = host
22
+ @port = port
23
+ @socket = socket
23
24
  init_fallback if user.nil? or pass.nil?
24
25
  skip_resource("Can't run MySQL SQL checks without authentication") if @user.nil? or @pass.nil?
25
26
  end
@@ -30,12 +31,20 @@ module Inspec::Resources
30
31
  escaped_query = q.gsub(/\\/, '\\\\').gsub(/"/, '\\"').gsub(/\$/, '\\$')
31
32
 
32
33
  # run the query
33
- cmd = inspec.command("mysql -u#{@user} -p#{@pass} -h #{@host} #{db} -s -e \"#{escaped_query}\"")
34
+ command = "mysql -u#{@user} -p#{@pass}"
35
+ if !@socket.nil?
36
+ command += " -S #{@socket}"
37
+ else
38
+ command += " -h #{@host}"
39
+ end
40
+ command += " --port #{@port}" unless @port.nil?
41
+ command += " #{db} -s -S #{@socket} -e \"#{escaped_query}\""
42
+
43
+ cmd = inspec.command(command)
34
44
  out = cmd.stdout + "\n" + cmd.stderr
35
- if out =~ /Can't connect to .* MySQL server/ or
36
- out.downcase =~ /^error/
45
+ if out =~ /Can't connect to .* MySQL server/ || out.downcase =~ /^error/
37
46
  # skip this test if the server can't run the query
38
- skip_resource("Can't connect to MySQL instance for SQL checks.")
47
+ warn("Can't connect to MySQL instance for SQL checks.")
39
48
  end
40
49
 
41
50
  # return the raw command output