inspec 0.9.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 (247) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.rubocop.yml +65 -0
  4. data/.travis.yml +23 -0
  5. data/CHANGELOG.md +38 -0
  6. data/Gemfile +33 -0
  7. data/LICENSE +201 -0
  8. data/MAINTAINERS.md +28 -0
  9. data/MAINTAINERS.toml +42 -0
  10. data/README.md +257 -0
  11. data/Rakefile +47 -0
  12. data/bin/inspec +109 -0
  13. data/docs/ctl_inspec.rst +195 -0
  14. data/docs/dsl_inspec.rst +182 -0
  15. data/docs/readme.rst +100 -0
  16. data/docs/resources.rst +4319 -0
  17. data/docs/template.rst +51 -0
  18. data/examples/test-kitchen/.kitchen.yml +20 -0
  19. data/examples/test-kitchen/Berksfile +3 -0
  20. data/examples/test-kitchen/Gemfile +21 -0
  21. data/examples/test-kitchen/README.md +27 -0
  22. data/examples/test-kitchen/metadata.rb +7 -0
  23. data/examples/test-kitchen/recipes/default.rb +6 -0
  24. data/examples/test-kitchen/recipes/nginx.rb +30 -0
  25. data/examples/test-kitchen/test/integration/default/web_spec.rb +28 -0
  26. data/inspec.gemspec +30 -0
  27. data/lib/inspec.rb +20 -0
  28. data/lib/inspec/backend.rb +42 -0
  29. data/lib/inspec/dsl.rb +151 -0
  30. data/lib/inspec/log.rb +34 -0
  31. data/lib/inspec/metadata.rb +79 -0
  32. data/lib/inspec/plugins.rb +9 -0
  33. data/lib/inspec/plugins/resource.rb +62 -0
  34. data/lib/inspec/profile.rb +138 -0
  35. data/lib/inspec/profile_context.rb +170 -0
  36. data/lib/inspec/resource.rb +76 -0
  37. data/lib/inspec/rspec_json_formatter.rb +27 -0
  38. data/lib/inspec/rule.rb +170 -0
  39. data/lib/inspec/runner.rb +154 -0
  40. data/lib/inspec/shell.rb +66 -0
  41. data/lib/inspec/targets.rb +9 -0
  42. data/lib/inspec/targets/core.rb +27 -0
  43. data/lib/inspec/targets/dir.rb +67 -0
  44. data/lib/inspec/targets/file.rb +29 -0
  45. data/lib/inspec/targets/folder.rb +43 -0
  46. data/lib/inspec/targets/tar.rb +34 -0
  47. data/lib/inspec/targets/url.rb +39 -0
  48. data/lib/inspec/targets/zip.rb +47 -0
  49. data/lib/inspec/version.rb +7 -0
  50. data/lib/matchers/matchers.rb +221 -0
  51. data/lib/resources/apache.rb +29 -0
  52. data/lib/resources/apache_conf.rb +113 -0
  53. data/lib/resources/apt.rb +140 -0
  54. data/lib/resources/audit_policy.rb +63 -0
  55. data/lib/resources/auditd_conf.rb +56 -0
  56. data/lib/resources/auditd_rules.rb +53 -0
  57. data/lib/resources/bond.rb +65 -0
  58. data/lib/resources/bridge.rb +114 -0
  59. data/lib/resources/command.rb +57 -0
  60. data/lib/resources/csv.rb +32 -0
  61. data/lib/resources/directory.rb +15 -0
  62. data/lib/resources/etc_group.rb +150 -0
  63. data/lib/resources/file.rb +110 -0
  64. data/lib/resources/gem.rb +46 -0
  65. data/lib/resources/group.rb +132 -0
  66. data/lib/resources/host.rb +143 -0
  67. data/lib/resources/inetd_conf.rb +56 -0
  68. data/lib/resources/interface.rb +127 -0
  69. data/lib/resources/iptables.rb +65 -0
  70. data/lib/resources/json.rb +64 -0
  71. data/lib/resources/kernel_module.rb +40 -0
  72. data/lib/resources/kernel_parameter.rb +55 -0
  73. data/lib/resources/limits_conf.rb +55 -0
  74. data/lib/resources/login_def.rb +60 -0
  75. data/lib/resources/mysql.rb +81 -0
  76. data/lib/resources/mysql_conf.rb +116 -0
  77. data/lib/resources/mysql_session.rb +52 -0
  78. data/lib/resources/npm.rb +44 -0
  79. data/lib/resources/ntp_conf.rb +58 -0
  80. data/lib/resources/oneget.rb +63 -0
  81. data/lib/resources/os.rb +22 -0
  82. data/lib/resources/os_env.rb +34 -0
  83. data/lib/resources/package.rb +169 -0
  84. data/lib/resources/parse_config.rb +75 -0
  85. data/lib/resources/passwd.rb +93 -0
  86. data/lib/resources/pip.rb +75 -0
  87. data/lib/resources/port.rb +296 -0
  88. data/lib/resources/postgres.rb +37 -0
  89. data/lib/resources/postgres_conf.rb +87 -0
  90. data/lib/resources/postgres_session.rb +59 -0
  91. data/lib/resources/processes.rb +57 -0
  92. data/lib/resources/registry_key.rb +54 -0
  93. data/lib/resources/script.rb +34 -0
  94. data/lib/resources/security_policy.rb +73 -0
  95. data/lib/resources/service.rb +379 -0
  96. data/lib/resources/ssh_conf.rb +75 -0
  97. data/lib/resources/user.rb +374 -0
  98. data/lib/resources/windows_feature.rb +77 -0
  99. data/lib/resources/yaml.rb +23 -0
  100. data/lib/resources/yum.rb +154 -0
  101. data/lib/utils/convert.rb +12 -0
  102. data/lib/utils/detect.rb +15 -0
  103. data/lib/utils/find_files.rb +36 -0
  104. data/lib/utils/hash.rb +13 -0
  105. data/lib/utils/modulator.rb +12 -0
  106. data/lib/utils/parser.rb +61 -0
  107. data/lib/utils/simpleconfig.rb +115 -0
  108. data/tasks/maintainers.rb +213 -0
  109. data/test/docker_run.rb +156 -0
  110. data/test/docker_test.rb +51 -0
  111. data/test/helper.rb +200 -0
  112. data/test/integration/.kitchen.yml +42 -0
  113. data/test/integration/Berksfile +4 -0
  114. data/test/integration/cookbooks/os_prepare/metadata.rb +8 -0
  115. data/test/integration/cookbooks/os_prepare/recipes/apt.rb +20 -0
  116. data/test/integration/cookbooks/os_prepare/recipes/default.rb +9 -0
  117. data/test/integration/cookbooks/os_prepare/recipes/file.rb +21 -0
  118. data/test/integration/cookbooks/os_prepare/recipes/package.rb +26 -0
  119. data/test/integration/default/_debug_spec.rb +1 -0
  120. data/test/integration/default/apt_spec.rb +42 -0
  121. data/test/integration/default/file_spec.rb +109 -0
  122. data/test/integration/default/group_spec.rb +32 -0
  123. data/test/integration/default/kernel_module_spec.rb +17 -0
  124. data/test/integration/default/kernel_parameter_spec.rb +56 -0
  125. data/test/integration/default/package_spec.rb +11 -0
  126. data/test/integration/default/service_spec.rb +28 -0
  127. data/test/integration/default/user_spec.rb +44 -0
  128. data/test/resource/command_test.rb +33 -0
  129. data/test/resource/dsl_test.rb +45 -0
  130. data/test/resource/file_test.rb +130 -0
  131. data/test/resource/ssh_config.rb +9 -0
  132. data/test/resource/sshd_config.rb +9 -0
  133. data/test/test-extra.yaml +11 -0
  134. data/test/test.yaml +11 -0
  135. data/test/unit/mock/cmd/Get-NetAdapter +24 -0
  136. data/test/unit/mock/cmd/GetUserAccount +33 -0
  137. data/test/unit/mock/cmd/GetWin32Group +23 -0
  138. data/test/unit/mock/cmd/PATH +1 -0
  139. data/test/unit/mock/cmd/Resolve-DnsName +26 -0
  140. data/test/unit/mock/cmd/Test-NetConnection +4 -0
  141. data/test/unit/mock/cmd/auditctl +7 -0
  142. data/test/unit/mock/cmd/auditpol +2 -0
  143. data/test/unit/mock/cmd/brew-info-jq +1 -0
  144. data/test/unit/mock/cmd/chage-l-root +7 -0
  145. data/test/unit/mock/cmd/dpkg-s-curl +21 -0
  146. data/test/unit/mock/cmd/dscl +5 -0
  147. data/test/unit/mock/cmd/etc-apt +7 -0
  148. data/test/unit/mock/cmd/find-etc-rc-d-name-S +12 -0
  149. data/test/unit/mock/cmd/find-net-interface +9 -0
  150. data/test/unit/mock/cmd/gem-list-local-a-q-rubocop +1 -0
  151. data/test/unit/mock/cmd/get-net-tcpconnection +24 -0
  152. data/test/unit/mock/cmd/get-netadapter-binding-bridge +4 -0
  153. data/test/unit/mock/cmd/get-package-firefox +30 -0
  154. data/test/unit/mock/cmd/get-package-ruby +18 -0
  155. data/test/unit/mock/cmd/get-service-dhcp +10 -0
  156. data/test/unit/mock/cmd/get-windows-feature +7 -0
  157. data/test/unit/mock/cmd/getent-hosts-example.com +1 -0
  158. data/test/unit/mock/cmd/getent-passwd-root +1 -0
  159. data/test/unit/mock/cmd/id-chartmann +1 -0
  160. data/test/unit/mock/cmd/id-root +1 -0
  161. data/test/unit/mock/cmd/initctl-show-config-ssh +3 -0
  162. data/test/unit/mock/cmd/initctl-status-ssh +1 -0
  163. data/test/unit/mock/cmd/iptables-s +6 -0
  164. data/test/unit/mock/cmd/launchctl-list +3 -0
  165. data/test/unit/mock/cmd/ls-1-etc-init.d +2 -0
  166. data/test/unit/mock/cmd/ls-sys-class-net-br +2 -0
  167. data/test/unit/mock/cmd/lsmod +2 -0
  168. data/test/unit/mock/cmd/lsof-np-itcp +4 -0
  169. data/test/unit/mock/cmd/netstat-tulpen +5 -0
  170. data/test/unit/mock/cmd/npm-ls-g--json-bower +9 -0
  171. data/test/unit/mock/cmd/pacman-qi-curl +21 -0
  172. data/test/unit/mock/cmd/ping-example.com +6 -0
  173. data/test/unit/mock/cmd/pip-show-jinja2 +11 -0
  174. data/test/unit/mock/cmd/ps-aux +3 -0
  175. data/test/unit/mock/cmd/pw-usershow-root-7 +1 -0
  176. data/test/unit/mock/cmd/reg_schedule +1 -0
  177. data/test/unit/mock/cmd/rpm-qia-curl +24 -0
  178. data/test/unit/mock/cmd/sbin_sysctl +1 -0
  179. data/test/unit/mock/cmd/secedit-export +7 -0
  180. data/test/unit/mock/cmd/service-e +2 -0
  181. data/test/unit/mock/cmd/service-sendmail-onestatus +3 -0
  182. data/test/unit/mock/cmd/service-sshd-status +1 -0
  183. data/test/unit/mock/cmd/sockstat +5 -0
  184. data/test/unit/mock/cmd/success +0 -0
  185. data/test/unit/mock/cmd/systemctl-show-all-sshd +6 -0
  186. data/test/unit/mock/cmd/win32_product +8 -0
  187. data/test/unit/mock/cmd/yum-repolist-all +52 -0
  188. data/test/unit/mock/files/auditd.conf +4 -0
  189. data/test/unit/mock/files/bond0 +37 -0
  190. data/test/unit/mock/files/etcgroup +3 -0
  191. data/test/unit/mock/files/example.csv +6 -0
  192. data/test/unit/mock/files/inetd.conf +2 -0
  193. data/test/unit/mock/files/kitchen.yml +7 -0
  194. data/test/unit/mock/files/limits.conf +5 -0
  195. data/test/unit/mock/files/login.defs +5 -0
  196. data/test/unit/mock/files/mysql.conf +8 -0
  197. data/test/unit/mock/files/mysql2.conf +2 -0
  198. data/test/unit/mock/files/ntp.conf +5 -0
  199. data/test/unit/mock/files/passwd +2 -0
  200. data/test/unit/mock/files/policyfile.lock.json +12 -0
  201. data/test/unit/mock/files/ssh_config +5 -0
  202. data/test/unit/mock/files/sshd_config +7 -0
  203. data/test/unit/mock/profiles/empty/metadata.rb +0 -0
  204. data/test/unit/mock/profiles/metadata/metadata.rb +1 -0
  205. data/test/unit/profile_context_test.rb +140 -0
  206. data/test/unit/profile_test.rb +49 -0
  207. data/test/unit/resources/apt_test.rb +46 -0
  208. data/test/unit/resources/audit_policy_test.rb +13 -0
  209. data/test/unit/resources/auditd_conf_test.rb +15 -0
  210. data/test/unit/resources/auditd_rules_test.rb +21 -0
  211. data/test/unit/resources/bond_test.rb +24 -0
  212. data/test/unit/resources/bridge_test.rb +56 -0
  213. data/test/unit/resources/csv_test.rb +35 -0
  214. data/test/unit/resources/etc_group_test.rb +37 -0
  215. data/test/unit/resources/gem_test.rb +20 -0
  216. data/test/unit/resources/group_test.rb +96 -0
  217. data/test/unit/resources/host_test.rb +38 -0
  218. data/test/unit/resources/inetd_conf_test.rb +15 -0
  219. data/test/unit/resources/interface_test.rb +54 -0
  220. data/test/unit/resources/iptables_test.rb +30 -0
  221. data/test/unit/resources/json_test.rb +36 -0
  222. data/test/unit/resources/kernel_module_test.rb +23 -0
  223. data/test/unit/resources/kernel_parameter_test.rb +13 -0
  224. data/test/unit/resources/limits_conf_test.rb +14 -0
  225. data/test/unit/resources/login_def_test.rb +16 -0
  226. data/test/unit/resources/mysql_conf_test.rb +14 -0
  227. data/test/unit/resources/npm_test.rb +20 -0
  228. data/test/unit/resources/ntp_conf_test.rb +16 -0
  229. data/test/unit/resources/oneget_test.rb +45 -0
  230. data/test/unit/resources/os_env_test.rb +13 -0
  231. data/test/unit/resources/package_test.rb +51 -0
  232. data/test/unit/resources/passwd_test.rb +24 -0
  233. data/test/unit/resources/pip_test.rb +15 -0
  234. data/test/unit/resources/port_test.rb +46 -0
  235. data/test/unit/resources/processes_test.rb +32 -0
  236. data/test/unit/resources/registry_key_test.rb +19 -0
  237. data/test/unit/resources/script_test.rb +19 -0
  238. data/test/unit/resources/security_policy_test.rb +16 -0
  239. data/test/unit/resources/service_test.rb +116 -0
  240. data/test/unit/resources/ssh_conf_test.rb +33 -0
  241. data/test/unit/resources/user_test.rb +93 -0
  242. data/test/unit/resources/windows_feature.rb +17 -0
  243. data/test/unit/resources/yaml_test.rb +34 -0
  244. data/test/unit/resources/yum_test.rb +68 -0
  245. data/test/unit/simpleconfig_test.rb +80 -0
  246. data/test/unit/utils/content_parser_test.rb +30 -0
  247. metadata +555 -0
@@ -0,0 +1,65 @@
1
+ # encoding: utf-8
2
+ # author: Christoph Hartmann
3
+ # author: Dominik Richter
4
+
5
+ # Usage:
6
+ # describe iptables do
7
+ # it { should have_rule('-P INPUT ACCEPT') }
8
+ # end
9
+ #
10
+ # The following serverspec sytax is not implemented:
11
+ # describe iptables do
12
+ # it { should have_rule('-P INPUT ACCEPT').with_table('mangle').with_chain('INPUT') }
13
+ # end
14
+ # Please use the new sytax:
15
+ # describe iptables(table:'mangle', chain: 'input') do
16
+ # it { should have_rule('-P INPUT ACCEPT') }
17
+ # end
18
+ #
19
+ # Note: Docker containers normally do not have iptables installed
20
+ #
21
+ # @see http://ipset.netfilter.org/iptables.man.html
22
+ # @see http://ipset.netfilter.org/iptables.man.html
23
+ # @see https://www.frozentux.net/iptables-tutorial/iptables-tutorial.html
24
+ class IpTables < Inspec.resource(1)
25
+ name 'iptables'
26
+
27
+ def initialize(params = {})
28
+ @table = params[:table] || nil
29
+ @chain = params[:chain] || nil
30
+
31
+ # we're done if we are on linux
32
+ return if inspec.os.linux?
33
+
34
+ # ensures, all calls are aborted for non-supported os
35
+ @iptables_cache = []
36
+ skip_resource 'The `iptables` resource is not supported on your OS yet.'
37
+ end
38
+
39
+ def has_rule?(rule = nil, _table = nil, _chain = nil)
40
+ found = false
41
+ retrieve_rules.each { |line|
42
+ # checks if the rule is part of the ruleset
43
+ # for now, we expect an excact match
44
+ found = true if line.downcase == rule.downcase
45
+ }
46
+ found
47
+ end
48
+
49
+ def retrieve_rules
50
+ return @iptables_cache if defined?(@iptables_cache)
51
+
52
+ # construct iptables command to read all rules
53
+ @table.nil? ? table_cmd = '' : table_cmd = " -t #{@table} "
54
+ @chain.nil? ? chain_cmd = '' : chain_cmd = " #{@chain}"
55
+ cmd = inspec.command(format('iptables %s -S %s', table_cmd, chain_cmd).strip)
56
+ return [] if cmd.exit_status.to_i != 0
57
+
58
+ # split rules, returns array or rules
59
+ @iptables_cache = cmd.stdout.chomp.split("\n")
60
+ end
61
+
62
+ def to_s
63
+ format('Iptables %s %s', @table.nil? ? '' : "table: #{@table}", @chain.nil? ? '' : "chain: #{@chain}").strip
64
+ end
65
+ end
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+ # author: Christoph Hartmann
3
+ # author: Dominik Richter
4
+
5
+ # Parses a json document
6
+ # Usage:
7
+ # describe json('policyfile.lock.json') do
8
+ # its('cookbook_locks.omnibus.version') { should eq('2.2.0') }
9
+ # end
10
+ class JsonConfig < Inspec.resource(1)
11
+ name 'json'
12
+
13
+ # make params readable
14
+ attr_reader :params
15
+
16
+ def initialize(path)
17
+ @path = path
18
+ @file_content = inspec.file(@path).content
19
+ @params = parse(@file_content)
20
+ end
21
+
22
+ def parse(content)
23
+ require 'json'
24
+ JSON.parse(content)
25
+ end
26
+
27
+ def extract_value(keys, value)
28
+ key = keys.shift
29
+ return nil if key.nil?
30
+
31
+ # check if key is a num, try to extract from array
32
+ if key.to_i.to_s == key
33
+ value = value[key.to_i]
34
+ # if value is an array, iterate over each child
35
+ elsif value.is_a?(Array)
36
+ value = value.map { |i|
37
+ extract_value([key], i)
38
+ }
39
+ # normal value extraction
40
+ else
41
+ value = value[key].nil? ? nil : value[key]
42
+ end
43
+
44
+ # check if further keys exist
45
+ if !keys.first.nil?
46
+ return extract_value(keys.clone, value)
47
+ else
48
+ return value
49
+ end
50
+ end
51
+
52
+ # Shorthand to retrieve a parameter name via `#its`.
53
+ # Example: describe json('file') { its('paramX') { should eq 'Y' } }
54
+ #
55
+ # @param [String] name name of the field to retrieve
56
+ # @return [Object] the value stored at this position
57
+ def method_missing(name)
58
+ @params[name.to_s]
59
+ end
60
+
61
+ def to_s
62
+ "Json #{@path}"
63
+ end
64
+ end
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+ # author: Christoph Hartmann
3
+ # author: Dominik Richter
4
+ # license: All rights reserved
5
+
6
+ # Verifies if a kernel module is loaded
7
+ # Usage:
8
+ # describe kernel_module('bridge') do
9
+ # it { should be_loaded }
10
+ # end
11
+ class KernelModule < Inspec.resource(1)
12
+ name 'kernel_module'
13
+
14
+ def initialize(modulename = nil)
15
+ @module = modulename
16
+
17
+ # this resource is only supported on Linux
18
+ return skip_resource 'The `kernel_parameter` resource is not supported on your OS.' if !inspec.os.linux?
19
+ end
20
+
21
+ def loaded?
22
+ # default lsmod command
23
+ lsmod_cmd = 'lsmod'
24
+ # special care for CentOS 5 and sudo
25
+ lsmod_cmd = '/sbin/lsmod' if inspec.os[:family] == 'centos' && inspec.os[:release].to_i == 5
26
+
27
+ # get list of all modules
28
+ cmd = inspec.command(lsmod_cmd)
29
+ return false if cmd.exit_status != 0
30
+
31
+ # check if module is loaded
32
+ re = Regexp.new('^'+Regexp.quote(@module)+'\s')
33
+ found = cmd.stdout.match(re)
34
+ !found.nil?
35
+ end
36
+
37
+ def to_s
38
+ "Kernel Module #{@module}"
39
+ end
40
+ end
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+ # author: Christoph Hartmann
3
+ # license: All rights reserved
4
+
5
+ # Verifies if a kernel parameter is set
6
+ # describe kernel_parameter('net.ipv4.conf.all.forwarding') do
7
+ # its(:value) { should eq 0 }
8
+ # end
9
+ class KernelParameter < Inspec.resource(1)
10
+ name 'kernel_parameter'
11
+
12
+ def initialize(parameter = nil)
13
+ @parameter = parameter
14
+
15
+ # this resource is only supported on Linux
16
+ return skip_resource 'The `kernel_parameter` resource is not supported on your OS.' if !inspec.os.linux?
17
+ end
18
+
19
+ def value
20
+ cmd = inspec.command("/sbin/sysctl -q -n #{@parameter}")
21
+ return nil if cmd.exit_status != 0
22
+ # remove whitespace
23
+ cmd = cmd.stdout.chomp.strip
24
+ # convert to number if possible
25
+ cmd = cmd.to_i if cmd.match(/^\d+$/)
26
+ cmd
27
+ end
28
+
29
+ def to_s
30
+ "Kernel Parameter #{@parameter}"
31
+ end
32
+ end
33
+
34
+ # for compatability with serverspec
35
+ # this is deprecated syntax and will be removed in future versions
36
+ class LinuxKernelParameter < KernelParameter
37
+ name 'linux_kernel_parameter'
38
+
39
+ def initialize(parameter)
40
+ super(parameter)
41
+ end
42
+
43
+ def value
44
+ deprecated
45
+ super()
46
+ end
47
+
48
+ def deprecated
49
+ warn '[DEPRECATION] `linux_kernel_parameter(parameter)` is deprecated. Please use `kernel_parameter(parameter)` instead.'
50
+ end
51
+
52
+ def to_s
53
+ "Kernel Parameter #{@parameter}"
54
+ end
55
+ end
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+ # copyright: 2015, Vulcano Security GmbH
3
+ # author: Christoph Hartmann
4
+ # author: Dominik Richter
5
+ # license: All rights reserved
6
+
7
+ require 'utils/simpleconfig'
8
+
9
+ # Usage:
10
+ #
11
+ # describe limits_conf do
12
+ # its('*') { should include ['hard','core','0'] }
13
+ # end
14
+
15
+ class LimitsConf < Inspec.resource(1)
16
+ name 'limits_conf'
17
+
18
+ def initialize(path = nil)
19
+ @conf_path = path || '/etc/security/limits.conf'
20
+ end
21
+
22
+ def method_missing(name)
23
+ read_params[name.to_s]
24
+ end
25
+
26
+ def read_params
27
+ return @params if defined?(@params)
28
+
29
+ # read the file
30
+ file = inspec.file(@conf_path)
31
+ if !file.file?
32
+ skip_resource "Can't find file \"#{@conf_path}\""
33
+ return @params = {}
34
+ end
35
+
36
+ content = file.content
37
+ if content.empty? && file.size > 0
38
+ skip_resource "Can't read file \"#{@conf_path}\""
39
+ return @params = {}
40
+ end
41
+
42
+ # parse the file
43
+ conf = SimpleConfig.new(
44
+ content,
45
+ assignment_re: /^\s*(\S+?)\s+(.*?)\s+(.*?)\s+(.*?)\s*$/,
46
+ key_vals: 3,
47
+ multiple_values: true,
48
+ )
49
+ @params = conf.params
50
+ end
51
+
52
+ def to_s
53
+ 'limits.conf'
54
+ end
55
+ end
@@ -0,0 +1,60 @@
1
+ # encoding: utf-8
2
+ # copyright: 2015, Vulcano Security GmbH
3
+ # author: Christoph Hartmann
4
+ # author: Dominik Richter
5
+ # license: All rights reserved
6
+
7
+ require 'utils/simpleconfig'
8
+
9
+ # Usage:
10
+ #
11
+ # describe login_def do
12
+ # its('UMASK') {
13
+ # should eq '077'
14
+ # }
15
+ #
16
+ # its('PASS_MAX_DAYS.to_i') {
17
+ # should be <= 90
18
+ # }
19
+ # end
20
+
21
+ class LoginDef < Inspec.resource(1)
22
+ name 'login_defs'
23
+
24
+ def initialize(path = nil)
25
+ @conf_path = path || '/etc/login.defs'
26
+ end
27
+
28
+ def method_missing(name)
29
+ read_params[name.to_s]
30
+ end
31
+
32
+ def read_params
33
+ return @params if defined?(@params)
34
+
35
+ # read the file
36
+ file = inspec.file(@conf_path)
37
+ if !file.file?
38
+ skip_resource "Can't find file \"#{@conf_path}\""
39
+ return @params = {}
40
+ end
41
+
42
+ content = file.content
43
+ if content.empty? && file.size > 0
44
+ skip_resource "Can't read file \"#{@conf_path}\""
45
+ return @params = {}
46
+ end
47
+
48
+ # parse the file
49
+ conf = SimpleConfig.new(
50
+ content,
51
+ assignment_re: /^\s*(\S+)\s+(\S*)\s*$/,
52
+ multiple_values: false,
53
+ )
54
+ @params = conf.params
55
+ end
56
+
57
+ def to_s
58
+ 'login.defs'
59
+ end
60
+ end
@@ -0,0 +1,81 @@
1
+ # encoding: utf-8
2
+ # copyright: 2015, Vulcano Security GmbH
3
+ # author: Dominik Richter
4
+ # author: Christoph Hartmann
5
+ # license: All rights reserved
6
+
7
+ class Mysql < Inspec.resource(1)
8
+ name 'mysql'
9
+
10
+ attr_reader :package, :service, :conf_dir, :conf_path, :data_dir, :log_dir, :log_path, :log_group, :log_dir_group
11
+ def initialize
12
+ # set OS-dependent filenames and paths
13
+ case inspec.os[:family]
14
+ when 'ubuntu', 'debian'
15
+ init_ubuntu
16
+ when 'redhat', 'fedora'
17
+ init_redhat
18
+ when 'arch'
19
+ init_arch
20
+ else
21
+ # TODO: could not detect
22
+ init_default
23
+ end
24
+ end
25
+
26
+ def init_ubuntu
27
+ @package = 'mysql-server'
28
+ @service = 'mysql'
29
+ @conf_path = '/etc/mysql/my.cnf'
30
+ @conf_dir = '/etc/mysql/'
31
+ @data_dir = '/var/lib/mysql/'
32
+ @log_dir = '/var/log/'
33
+ @log_path = '/var/log/mysql.log'
34
+ @log_group = 'adm'
35
+ case os[:release]
36
+ when '14.04'
37
+ @log_dir_group = 'syslog'
38
+ else
39
+ @log_dir_group = 'root'
40
+ end
41
+ end
42
+
43
+ def init_redhat
44
+ @package = 'mysql-server'
45
+ @service = 'mysqld'
46
+ @conf_path = '/etc/my.cnf'
47
+ @conf_dir = '/etc/'
48
+ @data_dir = '/var/lib/mysql/'
49
+ @log_dir = '/var/log/'
50
+ @log_path = '/var/log/mysqld.log'
51
+ @log_group = 'mysql'
52
+ @log_dir_group = 'root'
53
+ end
54
+
55
+ def init_arch
56
+ @package = 'mariadb'
57
+ @service = 'mysql'
58
+ @conf_path = '/etc/mysql/my.cnf'
59
+ @conf_dir = '/etc/mysql/'
60
+ @data_dir = '/var/lib/mysql/'
61
+ @log_dir = '/var/log/'
62
+ @log_path = '/var/log/mysql.log'
63
+ @log_group = 'mysql'
64
+ @log_dir_group = 'root'
65
+ end
66
+
67
+ def init_default
68
+ @service = 'mysqld'
69
+ @conf_path = '/etc/my.cnf'
70
+ @conf_dir = '/etc/'
71
+ @data_dir = '/var/lib/mysql/'
72
+ @log_dir = '/var/log/'
73
+ @log_path = '/var/log/mysqld.log'
74
+ @log_group = 'mysql'
75
+ @log_dir_group = 'root'
76
+ end
77
+
78
+ def to_s
79
+ 'MySQL'
80
+ end
81
+ end
@@ -0,0 +1,116 @@
1
+ # encoding: utf-8
2
+ # copyright: 2015, Vulcano Security GmbH
3
+ # author: Dominik Richter
4
+ # license: All rights reserved
5
+
6
+ require 'utils/simpleconfig'
7
+ require 'utils/find_files'
8
+ require 'utils/hash'
9
+ require 'resources/mysql'
10
+
11
+ class MysqlConfEntry
12
+ def initialize(path, params)
13
+ @params = params
14
+ @path = path
15
+ end
16
+
17
+ def method_missing(name, *_)
18
+ k = name.to_s
19
+ res = @params[k]
20
+ return true if res.nil? && @params.key?(k)
21
+ @params[k]
22
+ end
23
+
24
+ def to_s
25
+ "MySQL Config entry [#{@path.join(' ')}]"
26
+ end
27
+ end
28
+
29
+ class MysqlConf < Inspec.resource(1)
30
+ name 'mysql_conf'
31
+
32
+ include FindFiles
33
+
34
+ def initialize(conf_path = nil)
35
+ @conf_path = conf_path || inspec.mysql.conf_path
36
+ @files_contents = {}
37
+ @content = nil
38
+ @params = nil
39
+ read_content
40
+ end
41
+
42
+ def content
43
+ @content ||= read_content
44
+ end
45
+
46
+ def params(*opts)
47
+ @params || read_content
48
+ res = @params
49
+ opts.each do |opt|
50
+ res = res[opt] unless res.nil?
51
+ end
52
+ MysqlConfEntry.new(opts, res)
53
+ end
54
+
55
+ def method_missing(name)
56
+ @params || read_content
57
+ @params[name.to_s]
58
+ end
59
+
60
+ def read_content
61
+ @content = ''
62
+ @params = {}
63
+
64
+ # skip if the main configuration file doesn't exist
65
+ if !inspec.file(@conf_path).file?
66
+ return skip_resource "Can't find file \"#{@conf_path}\""
67
+ end
68
+ raw_conf = read_file(@conf_path)
69
+ if raw_conf.empty? && inspec.file(@conf_path).size > 0
70
+ return skip_resource("Can't read file \"#{@conf_path}\"")
71
+ end
72
+
73
+ to_read = [@conf_path]
74
+ until to_read.empty?
75
+ cur_file = to_read[0]
76
+ raw_conf = read_file(cur_file)
77
+ @content += raw_conf
78
+
79
+ params = SimpleConfig.new(raw_conf).params
80
+ @params = @params.deep_merge(params)
81
+
82
+ to_read = to_read.drop(1)
83
+ # see if there is more stuff to include
84
+
85
+ dir = File.dirname(cur_file)
86
+ to_read += include_files(dir, raw_conf).find_all do |fp|
87
+ not @files_contents.key? fp
88
+ end
89
+ end
90
+ #
91
+ @content
92
+ end
93
+
94
+ def include_files(reldir, conf)
95
+ files = conf.scan(/^!include\s+(.*)\s*/).flatten.compact.map { |x| abs_path(reldir, x) }
96
+ dirs = conf.scan(/^!includedir\s+(.*)\s*/).flatten.compact.map { |x| abs_path(reldir, x) }
97
+ dirs.map do |dir|
98
+ # @TODO: non local glob
99
+ files += find_files(dir, depth: 1, type: 'file')
100
+ end
101
+ files
102
+ end
103
+
104
+ def abs_path(dir, f)
105
+ return f if f.start_with? '/'
106
+ File.join(dir, f)
107
+ end
108
+
109
+ def read_file(path)
110
+ @files_contents[path] ||= inspec.file(path).content
111
+ end
112
+
113
+ def to_s
114
+ 'MySQL Configuration'
115
+ end
116
+ end