inspec 0.30.0 → 0.31.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 (316) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +50 -2
  3. data/Gemfile +2 -1
  4. data/docs/cli.rst +1 -17
  5. data/docs/resources.rst +128 -0
  6. data/docs/shell.rst +130 -0
  7. data/inspec.gemspec +3 -4
  8. data/lib/bundles/inspec-compliance/.kitchen.yml +0 -1
  9. data/lib/bundles/inspec-compliance/README.md +8 -3
  10. data/lib/bundles/inspec-compliance/api.rb +21 -6
  11. data/lib/bundles/inspec-compliance/bootstrap.sh +13 -9
  12. data/lib/bundles/inspec-compliance/cli.rb +23 -19
  13. data/lib/bundles/inspec-compliance/target.rb +1 -0
  14. data/lib/bundles/inspec-compliance/test/integration/default/cli.rb +42 -5
  15. data/lib/bundles/inspec-init/cli.rb +9 -0
  16. data/lib/bundles/inspec-supermarket/cli.rb +9 -0
  17. data/lib/bundles/inspec-supermarket/target.rb +2 -1
  18. data/lib/fetchers/local.rb +5 -2
  19. data/lib/fetchers/url.rb +1 -0
  20. data/lib/inspec/base_cli.rb +2 -1
  21. data/lib/inspec/cli.rb +14 -5
  22. data/lib/inspec/dependencies/dependency_set.rb +38 -0
  23. data/lib/inspec/dependencies/requirement.rb +103 -0
  24. data/lib/inspec/{dependencies.rb → dependencies/resolver.rb} +13 -132
  25. data/lib/inspec/dependencies/vendor_index.rb +98 -0
  26. data/lib/inspec/plugins/source_reader.rb +4 -0
  27. data/lib/inspec/profile.rb +2 -2
  28. data/lib/inspec/resource.rb +2 -0
  29. data/lib/inspec/runner.rb +13 -1
  30. data/lib/inspec/runner_mock.rb +4 -0
  31. data/lib/inspec/runner_rspec.rb +6 -2
  32. data/lib/inspec/shell.rb +22 -1
  33. data/lib/inspec/version.rb +1 -1
  34. data/lib/resources/iis_site.rb +107 -0
  35. data/lib/resources/port.rb +11 -4
  36. data/lib/resources/ssh_conf.rb +10 -2
  37. data/lib/resources/ssl.rb +94 -0
  38. data/lib/resources/xinetd.rb +11 -2
  39. data/lib/utils/parser.rb +6 -1
  40. metadata +17 -561
  41. data/lib/utils/hash_map.rb +0 -37
  42. data/tasks/maintainers.rb +0 -213
  43. data/test/bench/startup/startup.flat.txt +0 -1005
  44. data/test/bench/startup/startup.graph.html +0 -71958
  45. data/test/bench/startup/startup.grind.dat +0 -101602
  46. data/test/bench/startup/startup.stack.html +0 -24516
  47. data/test/bench/startup.flat.txt +0 -998
  48. data/test/bench/startup.graph.html +0 -71420
  49. data/test/bench/startup.grind.dat +0 -103554
  50. data/test/bench/startup.stack.html +0 -25015
  51. data/test/cookbooks/os_prepare/attributes/default.rb +0 -2
  52. data/test/cookbooks/os_prepare/files/empty.iso +0 -0
  53. data/test/cookbooks/os_prepare/files/example.csv +0 -7
  54. data/test/cookbooks/os_prepare/files/example.ini +0 -6
  55. data/test/cookbooks/os_prepare/files/example.json +0 -12
  56. data/test/cookbooks/os_prepare/files/example.yml +0 -7
  57. data/test/cookbooks/os_prepare/metadata.rb +0 -13
  58. data/test/cookbooks/os_prepare/recipes/_runit_service_centos.rb +0 -34
  59. data/test/cookbooks/os_prepare/recipes/_upstart_service_centos.rb +0 -25
  60. data/test/cookbooks/os_prepare/recipes/apache.rb +0 -14
  61. data/test/cookbooks/os_prepare/recipes/apt.rb +0 -20
  62. data/test/cookbooks/os_prepare/recipes/auditctl.rb +0 -8
  63. data/test/cookbooks/os_prepare/recipes/default.rb +0 -29
  64. data/test/cookbooks/os_prepare/recipes/file.rb +0 -46
  65. data/test/cookbooks/os_prepare/recipes/iptables.rb +0 -13
  66. data/test/cookbooks/os_prepare/recipes/json_yaml_csv_ini.rb +0 -34
  67. data/test/cookbooks/os_prepare/recipes/mount.rb +0 -33
  68. data/test/cookbooks/os_prepare/recipes/package.rb +0 -25
  69. data/test/cookbooks/os_prepare/recipes/postgres.rb +0 -20
  70. data/test/cookbooks/os_prepare/recipes/prep_container.rb +0 -15
  71. data/test/cookbooks/os_prepare/recipes/registry_key.rb +0 -87
  72. data/test/cookbooks/os_prepare/recipes/service.rb +0 -19
  73. data/test/cookbooks/os_prepare/templates/default/sv-default-svlog-run.erb +0 -2
  74. data/test/docker_run.rb +0 -162
  75. data/test/docker_test.rb +0 -58
  76. data/test/functional/helper.rb +0 -37
  77. data/test/functional/inheritance_test.rb +0 -62
  78. data/test/functional/inspec_archive_test.rb +0 -80
  79. data/test/functional/inspec_compliance_test.rb +0 -61
  80. data/test/functional/inspec_exec_json_test.rb +0 -122
  81. data/test/functional/inspec_exec_jsonmin_test.rb +0 -59
  82. data/test/functional/inspec_exec_test.rb +0 -123
  83. data/test/functional/inspec_json_profile_test.rb +0 -103
  84. data/test/functional/inspec_test.rb +0 -91
  85. data/test/helper.rb +0 -329
  86. data/test/integration/default/_debug_spec.rb +0 -8
  87. data/test/integration/default/apache_conf_spec.rb +0 -21
  88. data/test/integration/default/apt_spec.rb +0 -37
  89. data/test/integration/default/auditd_rules_spec.rb +0 -32
  90. data/test/integration/default/cmp_matcher_spec.rb +0 -115
  91. data/test/integration/default/csv_spec.rb +0 -11
  92. data/test/integration/default/etc_group_spec.rb +0 -29
  93. data/test/integration/default/file_spec.rb +0 -195
  94. data/test/integration/default/group_spec.rb +0 -59
  95. data/test/integration/default/ini_spec.rb +0 -11
  96. data/test/integration/default/iptables_spec.rb +0 -29
  97. data/test/integration/default/json_spec.rb +0 -11
  98. data/test/integration/default/kernel_module_spec.rb +0 -23
  99. data/test/integration/default/kernel_parameter_spec.rb +0 -60
  100. data/test/integration/default/mount_spec.rb +0 -19
  101. data/test/integration/default/os_spec.rb +0 -13
  102. data/test/integration/default/package_spec.rb +0 -30
  103. data/test/integration/default/port_spec.rb +0 -27
  104. data/test/integration/default/postgres_session_spec.rb +0 -13
  105. data/test/integration/default/powershell_spec.rb +0 -42
  106. data/test/integration/default/registry_key_spec.rb +0 -109
  107. data/test/integration/default/secpol_spec.rb +0 -11
  108. data/test/integration/default/service_spec.rb +0 -128
  109. data/test/integration/default/user_spec.rb +0 -96
  110. data/test/integration/default/vbscript_spec.rb +0 -22
  111. data/test/integration/default/wmi_spec.rb +0 -66
  112. data/test/integration/default/yaml_spec.rb +0 -11
  113. data/test/resource/command_test.rb +0 -33
  114. data/test/resource/dsl_test.rb +0 -45
  115. data/test/resource/file_test.rb +0 -146
  116. data/test/resource/ssh_config.rb +0 -9
  117. data/test/resource/sshd_config.rb +0 -9
  118. data/test/test-extra.yaml +0 -11
  119. data/test/test.yaml +0 -11
  120. data/test/unit/control_test.rb +0 -58
  121. data/test/unit/fetchers/local_test.rb +0 -67
  122. data/test/unit/fetchers/mock_test.rb +0 -43
  123. data/test/unit/fetchers/tar_test.rb +0 -36
  124. data/test/unit/fetchers/url_test.rb +0 -152
  125. data/test/unit/fetchers/zip_test.rb +0 -36
  126. data/test/unit/fetchers_test.rb +0 -65
  127. data/test/unit/metadata_test.rb +0 -137
  128. data/test/unit/mock/cmd/$env-PATH +0 -1
  129. data/test/unit/mock/cmd/Get-NetAdapter +0 -24
  130. data/test/unit/mock/cmd/GetUserAccount +0 -33
  131. data/test/unit/mock/cmd/GetWin32Group +0 -23
  132. data/test/unit/mock/cmd/Resolve-DnsName +0 -26
  133. data/test/unit/mock/cmd/Test-NetConnection +0 -4
  134. data/test/unit/mock/cmd/auditctl +0 -3
  135. data/test/unit/mock/cmd/auditctl-legacy +0 -7
  136. data/test/unit/mock/cmd/auditctl-s +0 -8
  137. data/test/unit/mock/cmd/auditpol +0 -2
  138. data/test/unit/mock/cmd/brew-info-jq +0 -1
  139. data/test/unit/mock/cmd/chage-l-root +0 -7
  140. data/test/unit/mock/cmd/dpkg-s-curl +0 -21
  141. data/test/unit/mock/cmd/dscl +0 -5
  142. data/test/unit/mock/cmd/env +0 -1
  143. data/test/unit/mock/cmd/etc-apt +0 -7
  144. data/test/unit/mock/cmd/find-apache2-conf-enabled +0 -1
  145. data/test/unit/mock/cmd/find-apache2-ports-conf +0 -1
  146. data/test/unit/mock/cmd/find-etc-rc-d-name-S +0 -12
  147. data/test/unit/mock/cmd/find-net-interface +0 -9
  148. data/test/unit/mock/cmd/find-xinetd.d +0 -2
  149. data/test/unit/mock/cmd/gem-list-local-a-q-rubocop +0 -1
  150. data/test/unit/mock/cmd/get-net-tcpconnection +0 -24
  151. data/test/unit/mock/cmd/get-netadapter-binding-bridge +0 -4
  152. data/test/unit/mock/cmd/get-package-firefox +0 -30
  153. data/test/unit/mock/cmd/get-package-ruby +0 -18
  154. data/test/unit/mock/cmd/get-service-dhcp +0 -10
  155. data/test/unit/mock/cmd/get-windows-feature +0 -7
  156. data/test/unit/mock/cmd/get-wmiobject +0 -9
  157. data/test/unit/mock/cmd/getent-hosts-example.com +0 -1
  158. data/test/unit/mock/cmd/getent-passwd-jfolmer +0 -1
  159. data/test/unit/mock/cmd/getent-passwd-root +0 -1
  160. data/test/unit/mock/cmd/hpux-netstat-inet +0 -10
  161. data/test/unit/mock/cmd/hpux-netstat-inet6 +0 -11
  162. data/test/unit/mock/cmd/id-chartmann +0 -1
  163. data/test/unit/mock/cmd/id-jfolmer +0 -1
  164. data/test/unit/mock/cmd/id-root +0 -1
  165. data/test/unit/mock/cmd/initctl--version +0 -5
  166. data/test/unit/mock/cmd/initctl-show-config-ssh +0 -3
  167. data/test/unit/mock/cmd/initctl-status-ssh +0 -1
  168. data/test/unit/mock/cmd/iptables-s +0 -6
  169. data/test/unit/mock/cmd/launchctl-list +0 -3
  170. data/test/unit/mock/cmd/logins-x +0 -4
  171. data/test/unit/mock/cmd/ls-1-etc-init.d +0 -2
  172. data/test/unit/mock/cmd/ls-sys-class-net-br +0 -2
  173. data/test/unit/mock/cmd/lsmod +0 -2
  174. data/test/unit/mock/cmd/lsof-nP-i-FpctPn +0 -63
  175. data/test/unit/mock/cmd/mount +0 -1
  176. data/test/unit/mock/cmd/mount-multiple +0 -2
  177. data/test/unit/mock/cmd/netstat-an.utf8 +0 -13
  178. data/test/unit/mock/cmd/netstat-tulpen +0 -6
  179. data/test/unit/mock/cmd/npm-ls-g--json-bower +0 -9
  180. data/test/unit/mock/cmd/pacman-qi-curl +0 -21
  181. data/test/unit/mock/cmd/ping-example.com +0 -6
  182. data/test/unit/mock/cmd/pip-show-jinja2 +0 -11
  183. data/test/unit/mock/cmd/pkg-info-system-file-system-zfs +0 -8
  184. data/test/unit/mock/cmd/pkginfo-l-SUNWzfsr +0 -7
  185. data/test/unit/mock/cmd/ps-aux +0 -5
  186. data/test/unit/mock/cmd/ps-auxZ +0 -3
  187. data/test/unit/mock/cmd/pw-usershow-root-7 +0 -1
  188. data/test/unit/mock/cmd/reg_schedule +0 -6
  189. data/test/unit/mock/cmd/rpm-qia-curl +0 -24
  190. data/test/unit/mock/cmd/s11-netstat-an-finet-finet6 +0 -32
  191. data/test/unit/mock/cmd/sbin_sysctl +0 -1
  192. data/test/unit/mock/cmd/secedit-export +0 -7
  193. data/test/unit/mock/cmd/service-e +0 -2
  194. data/test/unit/mock/cmd/service-sendmail-onestatus +0 -3
  195. data/test/unit/mock/cmd/service-sshd-status +0 -1
  196. data/test/unit/mock/cmd/sockstat +0 -5
  197. data/test/unit/mock/cmd/success +0 -0
  198. data/test/unit/mock/cmd/swlist-l-product +0 -1
  199. data/test/unit/mock/cmd/systemctl-show-all-dbus +0 -6
  200. data/test/unit/mock/cmd/systemctl-show-all-sshd +0 -7
  201. data/test/unit/mock/cmd/win32_product +0 -8
  202. data/test/unit/mock/cmd/yum-repolist-all +0 -52
  203. data/test/unit/mock/files/apache2.conf +0 -14
  204. data/test/unit/mock/files/auditd.conf +0 -4
  205. data/test/unit/mock/files/bond0 +0 -37
  206. data/test/unit/mock/files/etcgroup +0 -3
  207. data/test/unit/mock/files/example.csv +0 -6
  208. data/test/unit/mock/files/grub.conf +0 -21
  209. data/test/unit/mock/files/inetd.conf +0 -2
  210. data/test/unit/mock/files/kitchen.yml +0 -7
  211. data/test/unit/mock/files/limits.conf +0 -5
  212. data/test/unit/mock/files/login.defs +0 -5
  213. data/test/unit/mock/files/mysql.conf +0 -8
  214. data/test/unit/mock/files/mysql2.conf +0 -2
  215. data/test/unit/mock/files/ntp.conf +0 -5
  216. data/test/unit/mock/files/passwd +0 -2
  217. data/test/unit/mock/files/policyfile.lock.json +0 -12
  218. data/test/unit/mock/files/ports.conf +0 -6
  219. data/test/unit/mock/files/rootwrap.conf +0 -7
  220. data/test/unit/mock/files/serve-cgi-bin.conf +0 -20
  221. data/test/unit/mock/files/shadow +0 -2
  222. data/test/unit/mock/files/ssh_config +0 -5
  223. data/test/unit/mock/files/sshd_config +0 -7
  224. data/test/unit/mock/files/sysctl.conf +0 -7
  225. data/test/unit/mock/files/xinetd.conf +0 -9
  226. data/test/unit/mock/files/xinetd.d/.gitkeep +0 -0
  227. data/test/unit/mock/files/xinetd.d_chargen-dgram +0 -9
  228. data/test/unit/mock/files/xinetd.d_chargen-stream +0 -9
  229. data/test/unit/mock/profiles/complete-metadata/inspec.yml +0 -7
  230. data/test/unit/mock/profiles/complete-profile/controls/filesystem_spec.rb +0 -16
  231. data/test/unit/mock/profiles/complete-profile/inspec.yml +0 -10
  232. data/test/unit/mock/profiles/complete-profile/libraries/testlib.rb +0 -1
  233. data/test/unit/mock/profiles/empty-metadata/inspec.yml +0 -0
  234. data/test/unit/mock/profiles/legacy-complete-metadata/metadata.rb +0 -7
  235. data/test/unit/mock/profiles/legacy-complete-metadata/test/.gitkeep +0 -0
  236. data/test/unit/mock/profiles/legacy-empty-metadata/controls/.gitkeep +0 -0
  237. data/test/unit/mock/profiles/legacy-empty-metadata/metadata.rb +0 -0
  238. data/test/unit/mock/profiles/legacy-simple-metadata/metadata.rb +0 -1
  239. data/test/unit/mock/profiles/legacy-simple-metadata/test/.gitkeep +0 -0
  240. data/test/unit/mock/profiles/library/controls/filesystem_spec.rb +0 -7
  241. data/test/unit/mock/profiles/library/inspec.yml +0 -10
  242. data/test/unit/mock/profiles/library/libraries/gordonlib.rb +0 -2
  243. data/test/unit/mock/profiles/library/libraries/testlib.rb +0 -12
  244. data/test/unit/mock/profiles/resource-tiny/inspec.yml +0 -10
  245. data/test/unit/mock/profiles/resource-tiny/libraries/resource.rb +0 -3
  246. data/test/unit/mock/profiles/simple-metadata/inspec.yml +0 -1
  247. data/test/unit/mock/profiles/skippy-profile-os/controls/one.rb +0 -3
  248. data/test/unit/mock/profiles/skippy-profile-os/inspec.yml +0 -5
  249. data/test/unit/mock/profiles/spec_only/specfile.rb +0 -11
  250. data/test/unit/mock/profiles/supported_inspec/inspec.yml +0 -2
  251. data/test/unit/mock/profiles/unsupported_inspec/inspec.yml +0 -2
  252. data/test/unit/objects_test.rb +0 -65
  253. data/test/unit/plugin_test.rb +0 -44
  254. data/test/unit/plugins/resource_test.rb +0 -60
  255. data/test/unit/profile_context_test.rb +0 -345
  256. data/test/unit/profile_test.rb +0 -252
  257. data/test/unit/resources/apache_conf_test.rb +0 -31
  258. data/test/unit/resources/apt_test.rb +0 -46
  259. data/test/unit/resources/audit_policy_test.rb +0 -13
  260. data/test/unit/resources/auditd_conf_test.rb +0 -15
  261. data/test/unit/resources/auditd_rules_test.rb +0 -91
  262. data/test/unit/resources/bash_test.rb +0 -29
  263. data/test/unit/resources/bond_test.rb +0 -24
  264. data/test/unit/resources/bridge_test.rb +0 -56
  265. data/test/unit/resources/csv_test.rb +0 -35
  266. data/test/unit/resources/etc_group_test.rb +0 -37
  267. data/test/unit/resources/file_test.rb +0 -202
  268. data/test/unit/resources/gem_test.rb +0 -20
  269. data/test/unit/resources/group_test.rb +0 -96
  270. data/test/unit/resources/grub_conf_test.rb +0 -29
  271. data/test/unit/resources/host_test.rb +0 -38
  272. data/test/unit/resources/inetd_conf_test.rb +0 -15
  273. data/test/unit/resources/ini_test.rb +0 -16
  274. data/test/unit/resources/interface_test.rb +0 -54
  275. data/test/unit/resources/iptables_test.rb +0 -35
  276. data/test/unit/resources/json_test.rb +0 -36
  277. data/test/unit/resources/kernel_module_test.rb +0 -23
  278. data/test/unit/resources/kernel_parameter_test.rb +0 -13
  279. data/test/unit/resources/limits_conf_test.rb +0 -14
  280. data/test/unit/resources/login_def_test.rb +0 -16
  281. data/test/unit/resources/mount_test.rb +0 -26
  282. data/test/unit/resources/mysql_conf_test.rb +0 -14
  283. data/test/unit/resources/npm_test.rb +0 -20
  284. data/test/unit/resources/ntp_conf_test.rb +0 -16
  285. data/test/unit/resources/oneget_test.rb +0 -45
  286. data/test/unit/resources/os_env_test.rb +0 -18
  287. data/test/unit/resources/os_test.rb +0 -40
  288. data/test/unit/resources/package_test.rb +0 -87
  289. data/test/unit/resources/parse_config_test.rb +0 -26
  290. data/test/unit/resources/passwd_test.rb +0 -111
  291. data/test/unit/resources/pip_test.rb +0 -15
  292. data/test/unit/resources/port_test.rb +0 -165
  293. data/test/unit/resources/powershell_test.rb +0 -32
  294. data/test/unit/resources/processes_test.rb +0 -72
  295. data/test/unit/resources/registry_key_test.rb +0 -18
  296. data/test/unit/resources/security_policy_test.rb +0 -16
  297. data/test/unit/resources/service_test.rb +0 -305
  298. data/test/unit/resources/shadow_test.rb +0 -67
  299. data/test/unit/resources/ssh_conf_test.rb +0 -33
  300. data/test/unit/resources/user_test.rb +0 -124
  301. data/test/unit/resources/vbscript_test.rb +0 -18
  302. data/test/unit/resources/windows_feature.rb +0 -17
  303. data/test/unit/resources/wmi_test.rb +0 -42
  304. data/test/unit/resources/xinetd_test.rb +0 -60
  305. data/test/unit/resources/yaml_test.rb +0 -34
  306. data/test/unit/resources/yum_test.rb +0 -68
  307. data/test/unit/shell_detector_test.rb +0 -78
  308. data/test/unit/source_reader_test.rb +0 -17
  309. data/test/unit/source_readers/flat_test.rb +0 -61
  310. data/test/unit/source_readers/inspec_test.rb +0 -38
  311. data/test/unit/utils/filter_array_test.rb +0 -59
  312. data/test/unit/utils/filter_table_test.rb +0 -177
  313. data/test/unit/utils/find_files_test.rb +0 -23
  314. data/test/unit/utils/passwd_parser_test.rb +0 -32
  315. data/test/unit/utils/simpleconfig_test.rb +0 -80
  316. data/test/unit/utils/solaris_netstat_parser.rb +0 -124
data/lib/inspec/runner.rb CHANGED
@@ -66,6 +66,7 @@ module Inspec
66
66
  options['attributes'] = attributes
67
67
  end
68
68
 
69
+ # Returns the profile context used the profile at this target.
69
70
  def add_target(target, options = {})
70
71
  profile = Inspec::Profile.for_target(target, options)
71
72
  fail "Could not resolve #{target} to valid input." if profile.nil?
@@ -89,6 +90,7 @@ module Inspec
89
90
  true
90
91
  end
91
92
 
93
+ # Returns the profile context used to initialize this profile.
92
94
  def add_profile(profile, options = {})
93
95
  return if !options[:ignore_supports] && !supports_profile?(profile)
94
96
 
@@ -115,6 +117,8 @@ module Inspec
115
117
  Inspec::ProfileContext.new(profile_id, @backend, @conf.merge(options))
116
118
  end
117
119
 
120
+ # Returns the profile context used to evaluate the given content.
121
+ # Calling this method again will use a different context each time.
118
122
  def add_content(tests, libs, options = {})
119
123
  return if tests.nil? || tests.empty?
120
124
 
@@ -127,21 +131,29 @@ module Inspec
127
131
  profile.runner_context = ctx
128
132
  end
129
133
 
134
+ append_content(ctx, tests, libs, options)
135
+ end
136
+
137
+ # Returns the profile context used to evaluate the given content.
138
+ def append_content(ctx, tests, _libs, options = {})
130
139
  # evaluate the test content
131
140
  tests = [tests] unless tests.is_a? Array
132
141
  tests.each { |t| add_test_to_context(t, ctx) }
133
142
 
134
- # merge all collect all attributes
143
+ # merge and collect all attributes
135
144
  @attributes |= ctx.attributes
136
145
 
137
146
  # process the resulting rules
138
147
  filter_controls(ctx.rules, options[:controls]).each do |rule_id, rule|
139
148
  register_rule(rule_id, rule)
140
149
  end
150
+
151
+ ctx
141
152
  end
142
153
 
143
154
  def_delegator :@test_collector, :run
144
155
  def_delegator :@test_collector, :report
156
+ def_delegator :@test_collector, :reset
145
157
 
146
158
  private
147
159
 
@@ -7,6 +7,10 @@ module Inspec
7
7
  attr_reader :tests, :profiles
8
8
  attr_writer :backend
9
9
  def initialize
10
+ reset
11
+ end
12
+
13
+ def reset
10
14
  @tests = []
11
15
  @profiles = []
12
16
  end
@@ -15,6 +15,10 @@ module Inspec
15
15
  def initialize(conf)
16
16
  @conf = conf
17
17
  @formatter = nil
18
+ reset
19
+ end
20
+
21
+ def reset
18
22
  reset_tests
19
23
  configure_output
20
24
  end
@@ -87,8 +91,6 @@ module Inspec
87
91
  reporter.output_hash
88
92
  end
89
93
 
90
- private
91
-
92
94
  # Empty the list of registered tests.
93
95
  #
94
96
  # @return [nil]
@@ -98,6 +100,8 @@ module Inspec
98
100
  RSpec.configuration.reset
99
101
  end
100
102
 
103
+ private
104
+
101
105
  FORMATTERS = {
102
106
  'json-min' => 'InspecRspecMiniJson',
103
107
  'json' => 'InspecRspecJson',
data/lib/inspec/shell.rb CHANGED
@@ -5,6 +5,9 @@
5
5
  require 'rspec/core/formatters/base_text_formatter'
6
6
 
7
7
  module Inspec
8
+ # A pry based shell for inspec. Given a runner (with a configured backend and
9
+ # all that jazz), this shell will produce a pry shell from which you can run
10
+ # inspec/ruby commands that will be run within the context of the runner.
8
11
  class Shell
9
12
  def initialize(runner)
10
13
  @runner = runner
@@ -17,7 +20,6 @@ module Inspec
17
20
  # store context to run commands in this context
18
21
  c = { content: 'binding.pry', ref: nil, line: nil }
19
22
  @runner.add_content(c, [])
20
- @runner.run
21
23
  end
22
24
 
23
25
  def configure_pry
@@ -38,6 +40,25 @@ module Inspec
38
40
  Pry.hooks.add_hook(:before_session, :intro) do
39
41
  intro
40
42
  end
43
+
44
+ # execute describe blocks
45
+ Pry.hooks.add_hook(:after_eval, 'run_controls') do |output, _binding, _pry_|
46
+ next unless output.is_a?(Inspec::Rule)
47
+ # reset tests, register the control and execute the runner
48
+ @runner.reset
49
+ @runner.method(:register_rule).call(output.id, output)
50
+ @runner.run
51
+ end
52
+
53
+ # Don't print out control class inspection when the user uses DSL methods.
54
+ # Instead produce a result of evaluating their control.
55
+ Pry.config.print = proc do |_output, value, pry_|
56
+ next if value.is_a?(Inspec::Rule)
57
+ pry_.pager.open do |pager|
58
+ pager.print pry_.config.output_prefix
59
+ Pry::ColorPrinter.pp(value, pager, Pry::Terminal.width! - 1)
60
+ end
61
+ end
41
62
  end
42
63
 
43
64
  def readline_ignore(code)
@@ -3,5 +3,5 @@
3
3
  # author: Christoph Hartmann
4
4
 
5
5
  module Inspec
6
- VERSION = '0.30.0'.freeze
6
+ VERSION = '0.31.0'.freeze
7
7
  end
@@ -0,0 +1,107 @@
1
+ # encoding: utf-8
2
+ # check for site in IIS
3
+ # Usage:
4
+ # describe iis_site('Default Web Site') do
5
+ # it{ should exist }
6
+ # it{ should be_running }
7
+ # it{ should be_in_app_pool('Default App Pool') }
8
+ # it{ should have_path('C:\\inetpub\wwwroot\\DefaultWebSite') }
9
+ # it{ should have_binding('https :443:www.contoso.com sslFlags=0') }
10
+ # it{ should have_binding('net.pipe *') }
11
+ # end
12
+ #
13
+ # Note: this is only supported in windows 2012 and later
14
+
15
+ module Inspec::Resources
16
+ class IisSite < Inspec.resource(1)
17
+ name 'iis_site'
18
+ desc 'Tests IIS site configuration on windows. Supported in server 2012+ only'
19
+ example "
20
+ describe iis_site('Default Web Site') do
21
+ it { should exist }
22
+ it { should be_running }
23
+ it { should have_app_pool('DefaultAppPool') }
24
+ it { should have_binding('https :443:www.contoso.com sslFlags=0') }
25
+ it { should have_binding('net.pipe *') }
26
+ it { should have_path('C:\\inetpub\\wwwroot') }
27
+ end
28
+ "
29
+
30
+ def initialize(site_name)
31
+ @site_name = site_name
32
+ @cache = nil
33
+
34
+ @site_provider = SiteProvider.new(inspec)
35
+
36
+ # verify that this resource is only supported on Windows
37
+ return skip_resource 'The `iis_site` resource is not supported on your OS.' if inspec.os[:family] != 'windows'
38
+ end
39
+
40
+ def exists?
41
+ !iis_site.nil? && !iis_site[:name].nil?
42
+ end
43
+
44
+ def running?
45
+ iis_site.nil? ? false : (iis_site[:state] == 'Started')
46
+ end
47
+
48
+ def has_app_pool?(app_pool)
49
+ iis_site.nil? ? false : iis_site[:app_pool] == app_pool
50
+ end
51
+
52
+ def has_path?(path)
53
+ iis_site.nil? ? false : iis_site[:path] == path
54
+ end
55
+
56
+ def has_binding?(binding)
57
+ iis_site.nil? ? false : (iis_site[:bindings].include? binding)
58
+ end
59
+
60
+ def to_s
61
+ "iis_site '#{@site_name}'"
62
+ end
63
+
64
+ def iis_site
65
+ return @cache if !@cache.nil?
66
+ @cache = @site_provider.iis_site(@site_name) if !@site_provider.nil?
67
+ end
68
+ end
69
+
70
+ class SiteProvider
71
+ attr_reader :inspec
72
+
73
+ def initialize(inspec)
74
+ @inspec = inspec
75
+ end
76
+
77
+ # want to populate everything using one powershell command here and spit it out as json
78
+ def iis_site(name)
79
+ command = "Get-Website '#{name}' | select-object -Property Name,State,PhysicalPath,bindings,ApplicationPool | ConvertTo-Json"
80
+ cmd = @inspec.command(command)
81
+
82
+ begin
83
+ site = JSON.parse(cmd.stdout)
84
+ rescue JSON::ParserError => _e
85
+ return nil
86
+ end
87
+
88
+ bindings_array = site['bindings']['Collection'].map { |k, _str|
89
+ k['protocol'] <<
90
+ ' ' <<
91
+ k['bindingInformation'] <<
92
+ (k['protocol'] == 'https' ? ' sslFlags=' << flags : '')
93
+ }
94
+
95
+ # map our values to a hash table
96
+ info = {
97
+ name: site['name'],
98
+ state: site['state'],
99
+ path: site['physicalPath'],
100
+ bindings: bindings_array,
101
+ app_pool: site['applicationPool'],
102
+ }
103
+
104
+ info
105
+ end
106
+ end
107
+ end
@@ -122,13 +122,13 @@ module Inspec::Resources
122
122
  # @see https://connect.microsoft.com/PowerShell/feedback/details/1349420/get-nettcpconnection-does-not-show-processid
123
123
  class WindowsPorts < PortsInfo
124
124
  def info
125
- powershell_info || netstat_info
125
+ netstat_info || powershell_info
126
126
  end
127
127
 
128
128
  private
129
129
 
130
130
  def powershell_info
131
- cmd = inspec.command('Get-NetTCPConnection | Select-Object -Property State, Caption, Description, LocalAddress, LocalPort, RemoteAddress, RemotePort, DisplayName, Status | ConvertTo-Json')
131
+ cmd = inspec.command('Get-NetTCPConnection -state Listen | Select-Object -Property State, Caption, Description, LocalAddress, LocalPort, RemoteAddress, RemotePort, DisplayName, Status | ConvertTo-Json')
132
132
  return nil if cmd.exit_status != 0
133
133
 
134
134
  entries = JSON.parse(cmd.stdout)
@@ -146,14 +146,21 @@ module Inspec::Resources
146
146
  end
147
147
 
148
148
  def netstat_info
149
- cmd = inspec.command('netstat -an')
149
+ # retrieve processes grepping by LISTENING state with 0 lines before and 1 after to catch the process name
150
+ # also UDP ports have nothing in the State column
151
+ cmd = inspec.command('netstat -anbo | Select-String -CaseSensitive -pattern "^\s+UDP|\s+LISTENING\s+\d+$" -context 0,1')
150
152
  return nil if cmd.exit_status != 0
151
- lines = cmd.stdout.scan(/^\s*(tcp\S*|udp\S*)\s+(\S+):(\d+)\s+/i)
153
+ lines = cmd.stdout.scan(/^>\s*(tcp\S*|udp\S*)\s+(\S+):(\d+)\s+(\S+)\s+(\S*)\s+(\d+)\s+(.+)/i)
152
154
  lines.map do |line|
155
+ pid = line[5].to_i
156
+ process = line[6].delete('[').delete(']').strip
157
+ process = 'System' if process == 'Can not obtain ownership information' && pid == 4
153
158
  {
154
159
  'port' => line[2].to_i,
155
160
  'address' => line[1].delete('[').delete(']'),
156
161
  'protocol' => line[0].downcase,
162
+ 'pid' => pid,
163
+ 'process' => process,
157
164
  }
158
165
  end
159
166
  end
@@ -32,8 +32,16 @@ module Inspec::Resources
32
32
  end
33
33
  end
34
34
 
35
+ def convert_hash(hash)
36
+ new_hash = {}
37
+ hash.each do |k, v|
38
+ new_hash[k.downcase] = v
39
+ end
40
+ new_hash
41
+ end
42
+
35
43
  def method_missing(name)
36
- param = read_params[name.to_s]
44
+ param = read_params[name.to_s.downcase]
37
45
  return nil if param.nil?
38
46
  # extract first value if we have only one value in array
39
47
  return param[0] if param.length == 1
@@ -69,7 +77,7 @@ module Inspec::Resources
69
77
  assignment_re: /^\s*(\S+?)\s+(.*?)\s*$/,
70
78
  multiple_values: true,
71
79
  )
72
- @params = conf.params
80
+ @params = convert_hash(conf.params)
73
81
  end
74
82
  end
75
83
 
@@ -0,0 +1,94 @@
1
+ # encoding: utf-8
2
+ # copyright: 2015, Chef Software Inc.
3
+ # license: All rights reserved
4
+ # author: Dominik Richter
5
+ # author: Christoph Hartmann
6
+
7
+ require 'sslshake'
8
+ require 'utils/filter'
9
+
10
+ # Custom resource based on the InSpec resource DSL
11
+ class SSL < Inspec.resource(1)
12
+ name 'ssl'
13
+
14
+ desc "
15
+ SSL test resource
16
+ "
17
+
18
+ example "
19
+ describe ssl(port: 443) do
20
+ it { should be_enabled }
21
+ end
22
+
23
+ # protocols: ssl2, ssl3, tls1.0, tls1.1, tls1.2
24
+ describe ssl(port: 443).protocols('ssl2') do
25
+ it { should_not be_enabled }
26
+ end
27
+
28
+ # any ciphers, filter by name or regex
29
+ describe ssl(port: 443).ciphers(/rc4/i) do
30
+ it { should_not be_enabled }
31
+ end
32
+ "
33
+
34
+ VERSIONS = [
35
+ 'ssl2',
36
+ 'ssl3',
37
+ 'tls1.0',
38
+ 'tls1.1',
39
+ 'tls1.2',
40
+ ].freeze
41
+
42
+ attr_reader :host, :port
43
+
44
+ def initialize(opts = {})
45
+ @host = opts[:host] ||
46
+ inspec.backend.instance_variable_get(:@hostname)
47
+ if @host.nil? && inspec.backend.class.to_s == 'Train::Transports::Local::Connection'
48
+ @host = 'localhost'
49
+ end
50
+ if @host.nil?
51
+ fail 'Cannot determine host for SSL test. Please specify it or use a different target.'
52
+ end
53
+ @port = opts[:port] || 443
54
+ @timeout = opts[:timeout]
55
+ @retries = opts[:retries]
56
+ end
57
+
58
+ filter = FilterTable.create
59
+ filter.add_accessor(:where)
60
+ .add_accessor(:entries)
61
+ .add(:ciphers, field: 'cipher')
62
+ .add(:protocols, field: 'protocol')
63
+ .add(:enabled?) { |x| x.handshake.values.any? { |i| i['success'] } }
64
+ .add(:handshake) { |x|
65
+ groups = x.entries.group_by(&:protocol)
66
+ res = groups.map do |proto, e|
67
+ [proto, SSLShake.hello(x.resource.host, port: x.resource.port,
68
+ protocol: proto, ciphers: e.map(&:cipher),
69
+ timeout: @timeout, retries: @retries)]
70
+ end
71
+ Hash[res]
72
+ }
73
+ .connect(self, :scan_config)
74
+
75
+ def to_s
76
+ "SSL/TLS on #{@host}:#{@port}"
77
+ end
78
+
79
+ private
80
+
81
+ def scan_config
82
+ [
83
+ { 'protocol' => 'ssl2', 'ciphers' => SSLShake::SSLv2::CIPHERS.keys },
84
+ { 'protocol' => 'ssl3', 'ciphers' => SSLShake::TLS::SSL3_CIPHERS.keys },
85
+ { 'protocol' => 'tls1.0', 'ciphers' => SSLShake::TLS::TLS10_CIPHERS.keys },
86
+ { 'protocol' => 'tls1.1', 'ciphers' => SSLShake::TLS::TLS10_CIPHERS.keys },
87
+ { 'protocol' => 'tls1.2', 'ciphers' => SSLShake::TLS::TLS_CIPHERS.keys },
88
+ ].map do |line|
89
+ line['ciphers'].map do |cipher|
90
+ { 'protocol' => line['protocol'], 'cipher' => cipher }
91
+ end
92
+ end.flatten
93
+ end
94
+ end
@@ -66,17 +66,26 @@ module Inspec::Resources
66
66
  def read_params
67
67
  return {} if read_content.nil?
68
68
  flat_params = parse_xinetd(read_content)
69
+ # we need to map service data in order to use it with filtertable
69
70
  params = { 'services' => {} }
70
71
 
71
- # parse services that were defined:
72
+ # map services that were defined and map it to the service hash
72
73
  flat_params.each do |k, v|
73
74
  name = k[/^service (.+)$/, 1]
75
+ # its not a service, no change required
74
76
  if name.nil?
75
77
  params[k] = v
78
+ # handle service entries
76
79
  else
80
+ # store service
77
81
  params['services'][name] = v
82
+
78
83
  # add the service identifier to its parameters
79
- v.each { |service| service.params['service'] = name }
84
+ if v.is_a?(Array)
85
+ v.each { |service| service.params['service'] = name }
86
+ else
87
+ v.params['service'] = name
88
+ end
80
89
  end
81
90
  end
82
91
  params
data/lib/utils/parser.rb CHANGED
@@ -9,8 +9,9 @@ module PasswdParser
9
9
  # @return [Array] Collection of passwd entries
10
10
  def parse_passwd(content)
11
11
  content.to_s.split("\n").map do |line|
12
+ next if line[0] == '#'
12
13
  parse_passwd_line(line)
13
- end
14
+ end.compact
14
15
  end
15
16
 
16
17
  # Parse a line of /etc/passwd
@@ -178,6 +179,7 @@ module SolarisNetstatParser
178
179
  end
179
180
  end
180
181
 
182
+ # This parser for xinetd (extended Internet daemon) configuration files
181
183
  module XinetdParser
182
184
  def xinetd_include_dir(dir)
183
185
  return [] if dir.nil?
@@ -197,10 +199,12 @@ module XinetdParser
197
199
  simple_conf = []
198
200
  rest = raw
199
201
  until rest.empty?
202
+ # extract content line
200
203
  nl = rest.index("\n") || (rest.length-1)
201
204
  comment = rest.index('#') || (rest.length-1)
202
205
  dst_idx = (comment < nl) ? comment : nl
203
206
  inner_line = (dst_idx == 0) ? '' : rest[0..dst_idx-1].strip
207
+ # update unparsed content
204
208
  rest = rest[nl+1..-1]
205
209
  next if inner_line.empty?
206
210
 
@@ -212,6 +216,7 @@ module XinetdParser
212
216
  simple_conf = []
213
217
  rest = rest[rest.index("\n")+1..-1]
214
218
  elsif cur_group.nil?
219
+ # parse all included files
215
220
  others = xinetd_include_dir(inner_line[/includedir (.+)/, 1])
216
221
 
217
222
  # complex merging of included configurations, as multiple services