inspec-core 2.1.67

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 (412) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +3136 -0
  3. data/Gemfile +56 -0
  4. data/LICENSE +14 -0
  5. data/MAINTAINERS.md +33 -0
  6. data/MAINTAINERS.toml +52 -0
  7. data/README.md +453 -0
  8. data/bin/inspec +12 -0
  9. data/docs/.gitignore +2 -0
  10. data/docs/README.md +40 -0
  11. data/docs/dev/control-eval.md +62 -0
  12. data/docs/dsl_inspec.md +258 -0
  13. data/docs/dsl_resource.md +100 -0
  14. data/docs/glossary.md +99 -0
  15. data/docs/habitat.md +192 -0
  16. data/docs/inspec_and_friends.md +114 -0
  17. data/docs/matchers.md +169 -0
  18. data/docs/migration.md +293 -0
  19. data/docs/platforms.md +119 -0
  20. data/docs/plugin_kitchen_inspec.md +50 -0
  21. data/docs/profiles.md +378 -0
  22. data/docs/reporters.md +105 -0
  23. data/docs/resources/aide_conf.md.erb +76 -0
  24. data/docs/resources/apache.md.erb +67 -0
  25. data/docs/resources/apache_conf.md.erb +68 -0
  26. data/docs/resources/apt.md.erb +71 -0
  27. data/docs/resources/audit_policy.md.erb +47 -0
  28. data/docs/resources/auditd.md.erb +79 -0
  29. data/docs/resources/auditd_conf.md.erb +68 -0
  30. data/docs/resources/bash.md.erb +75 -0
  31. data/docs/resources/bond.md.erb +90 -0
  32. data/docs/resources/bridge.md.erb +57 -0
  33. data/docs/resources/bsd_service.md.erb +67 -0
  34. data/docs/resources/chocolatey_package.md.erb +58 -0
  35. data/docs/resources/command.md.erb +138 -0
  36. data/docs/resources/cpan.md.erb +79 -0
  37. data/docs/resources/cran.md.erb +64 -0
  38. data/docs/resources/crontab.md.erb +89 -0
  39. data/docs/resources/csv.md.erb +54 -0
  40. data/docs/resources/dh_params.md.erb +205 -0
  41. data/docs/resources/directory.md.erb +30 -0
  42. data/docs/resources/docker.md.erb +219 -0
  43. data/docs/resources/docker_container.md.erb +103 -0
  44. data/docs/resources/docker_image.md.erb +94 -0
  45. data/docs/resources/docker_service.md.erb +114 -0
  46. data/docs/resources/elasticsearch.md.erb +242 -0
  47. data/docs/resources/etc_fstab.md.erb +125 -0
  48. data/docs/resources/etc_group.md.erb +75 -0
  49. data/docs/resources/etc_hosts.md.erb +78 -0
  50. data/docs/resources/etc_hosts_allow.md.erb +74 -0
  51. data/docs/resources/etc_hosts_deny.md.erb +74 -0
  52. data/docs/resources/file.md.erb +526 -0
  53. data/docs/resources/filesystem.md.erb +41 -0
  54. data/docs/resources/firewalld.md.erb +107 -0
  55. data/docs/resources/gem.md.erb +79 -0
  56. data/docs/resources/group.md.erb +61 -0
  57. data/docs/resources/grub_conf.md.erb +101 -0
  58. data/docs/resources/host.md.erb +86 -0
  59. data/docs/resources/http.md.erb +197 -0
  60. data/docs/resources/iis_app.md.erb +122 -0
  61. data/docs/resources/iis_site.md.erb +135 -0
  62. data/docs/resources/inetd_conf.md.erb +94 -0
  63. data/docs/resources/ini.md.erb +76 -0
  64. data/docs/resources/interface.md.erb +58 -0
  65. data/docs/resources/iptables.md.erb +64 -0
  66. data/docs/resources/json.md.erb +63 -0
  67. data/docs/resources/kernel_module.md.erb +120 -0
  68. data/docs/resources/kernel_parameter.md.erb +53 -0
  69. data/docs/resources/key_rsa.md.erb +85 -0
  70. data/docs/resources/launchd_service.md.erb +57 -0
  71. data/docs/resources/limits_conf.md.erb +75 -0
  72. data/docs/resources/login_defs.md.erb +71 -0
  73. data/docs/resources/mount.md.erb +69 -0
  74. data/docs/resources/mssql_session.md.erb +60 -0
  75. data/docs/resources/mysql_conf.md.erb +99 -0
  76. data/docs/resources/mysql_session.md.erb +74 -0
  77. data/docs/resources/nginx.md.erb +79 -0
  78. data/docs/resources/nginx_conf.md.erb +138 -0
  79. data/docs/resources/npm.md.erb +60 -0
  80. data/docs/resources/ntp_conf.md.erb +60 -0
  81. data/docs/resources/oneget.md.erb +53 -0
  82. data/docs/resources/oracledb_session.md.erb +52 -0
  83. data/docs/resources/os.md.erb +141 -0
  84. data/docs/resources/os_env.md.erb +91 -0
  85. data/docs/resources/package.md.erb +120 -0
  86. data/docs/resources/packages.md.erb +67 -0
  87. data/docs/resources/parse_config.md.erb +103 -0
  88. data/docs/resources/parse_config_file.md.erb +138 -0
  89. data/docs/resources/passwd.md.erb +141 -0
  90. data/docs/resources/pip.md.erb +67 -0
  91. data/docs/resources/port.md.erb +137 -0
  92. data/docs/resources/postgres_conf.md.erb +79 -0
  93. data/docs/resources/postgres_hba_conf.md.erb +93 -0
  94. data/docs/resources/postgres_ident_conf.md.erb +76 -0
  95. data/docs/resources/postgres_session.md.erb +69 -0
  96. data/docs/resources/powershell.md.erb +102 -0
  97. data/docs/resources/processes.md.erb +109 -0
  98. data/docs/resources/rabbitmq_config.md.erb +41 -0
  99. data/docs/resources/registry_key.md.erb +158 -0
  100. data/docs/resources/runit_service.md.erb +57 -0
  101. data/docs/resources/security_policy.md.erb +47 -0
  102. data/docs/resources/service.md.erb +121 -0
  103. data/docs/resources/shadow.md.erb +146 -0
  104. data/docs/resources/ssh_config.md.erb +73 -0
  105. data/docs/resources/sshd_config.md.erb +83 -0
  106. data/docs/resources/ssl.md.erb +119 -0
  107. data/docs/resources/sys_info.md.erb +42 -0
  108. data/docs/resources/systemd_service.md.erb +57 -0
  109. data/docs/resources/sysv_service.md.erb +57 -0
  110. data/docs/resources/upstart_service.md.erb +57 -0
  111. data/docs/resources/user.md.erb +140 -0
  112. data/docs/resources/users.md.erb +127 -0
  113. data/docs/resources/vbscript.md.erb +55 -0
  114. data/docs/resources/virtualization.md.erb +57 -0
  115. data/docs/resources/windows_feature.md.erb +47 -0
  116. data/docs/resources/windows_hotfix.md.erb +53 -0
  117. data/docs/resources/windows_task.md.erb +95 -0
  118. data/docs/resources/wmi.md.erb +81 -0
  119. data/docs/resources/x509_certificate.md.erb +151 -0
  120. data/docs/resources/xinetd_conf.md.erb +156 -0
  121. data/docs/resources/xml.md.erb +85 -0
  122. data/docs/resources/yaml.md.erb +69 -0
  123. data/docs/resources/yum.md.erb +98 -0
  124. data/docs/resources/zfs_dataset.md.erb +53 -0
  125. data/docs/resources/zfs_pool.md.erb +47 -0
  126. data/docs/ruby_usage.md +203 -0
  127. data/docs/shared/matcher_be.md.erb +1 -0
  128. data/docs/shared/matcher_cmp.md.erb +43 -0
  129. data/docs/shared/matcher_eq.md.erb +3 -0
  130. data/docs/shared/matcher_include.md.erb +1 -0
  131. data/docs/shared/matcher_match.md.erb +1 -0
  132. data/docs/shell.md +217 -0
  133. data/examples/README.md +8 -0
  134. data/examples/inheritance/README.md +65 -0
  135. data/examples/inheritance/controls/example.rb +14 -0
  136. data/examples/inheritance/inspec.yml +15 -0
  137. data/examples/kitchen-ansible/.kitchen.yml +25 -0
  138. data/examples/kitchen-ansible/Gemfile +19 -0
  139. data/examples/kitchen-ansible/README.md +53 -0
  140. data/examples/kitchen-ansible/files/nginx.repo +6 -0
  141. data/examples/kitchen-ansible/tasks/main.yml +16 -0
  142. data/examples/kitchen-ansible/test/integration/default/default.yml +5 -0
  143. data/examples/kitchen-ansible/test/integration/default/web_spec.rb +28 -0
  144. data/examples/kitchen-chef/.kitchen.yml +20 -0
  145. data/examples/kitchen-chef/Berksfile +3 -0
  146. data/examples/kitchen-chef/Gemfile +19 -0
  147. data/examples/kitchen-chef/README.md +27 -0
  148. data/examples/kitchen-chef/metadata.rb +7 -0
  149. data/examples/kitchen-chef/recipes/default.rb +6 -0
  150. data/examples/kitchen-chef/recipes/nginx.rb +30 -0
  151. data/examples/kitchen-chef/test/integration/default/web_spec.rb +28 -0
  152. data/examples/kitchen-puppet/.kitchen.yml +23 -0
  153. data/examples/kitchen-puppet/Gemfile +20 -0
  154. data/examples/kitchen-puppet/Puppetfile +25 -0
  155. data/examples/kitchen-puppet/README.md +53 -0
  156. data/examples/kitchen-puppet/manifests/site.pp +33 -0
  157. data/examples/kitchen-puppet/metadata.json +11 -0
  158. data/examples/kitchen-puppet/modules/.gitkeep +0 -0
  159. data/examples/kitchen-puppet/test/integration/default/web_spec.rb +28 -0
  160. data/examples/meta-profile/README.md +37 -0
  161. data/examples/meta-profile/controls/example.rb +13 -0
  162. data/examples/meta-profile/inspec.yml +13 -0
  163. data/examples/profile-attribute.yml +2 -0
  164. data/examples/profile-attribute/README.md +14 -0
  165. data/examples/profile-attribute/controls/example.rb +11 -0
  166. data/examples/profile-attribute/inspec.yml +8 -0
  167. data/examples/profile-sensitive/README.md +29 -0
  168. data/examples/profile-sensitive/controls/sensitive-failures.rb +9 -0
  169. data/examples/profile-sensitive/controls/sensitive.rb +9 -0
  170. data/examples/profile-sensitive/inspec.yml +8 -0
  171. data/examples/profile/README.md +48 -0
  172. data/examples/profile/controls/example.rb +23 -0
  173. data/examples/profile/controls/gordon.rb +36 -0
  174. data/examples/profile/controls/meta.rb +34 -0
  175. data/examples/profile/inspec.yml +10 -0
  176. data/examples/profile/libraries/gordon_config.rb +59 -0
  177. data/inspec-core.gemspec +43 -0
  178. data/lib/bundles/README.md +3 -0
  179. data/lib/bundles/inspec-artifact.rb +7 -0
  180. data/lib/bundles/inspec-artifact/README.md +1 -0
  181. data/lib/bundles/inspec-artifact/cli.rb +277 -0
  182. data/lib/bundles/inspec-compliance.rb +16 -0
  183. data/lib/bundles/inspec-compliance/.kitchen.yml +20 -0
  184. data/lib/bundles/inspec-compliance/README.md +193 -0
  185. data/lib/bundles/inspec-compliance/api.rb +360 -0
  186. data/lib/bundles/inspec-compliance/api/login.rb +193 -0
  187. data/lib/bundles/inspec-compliance/bootstrap.sh +41 -0
  188. data/lib/bundles/inspec-compliance/cli.rb +260 -0
  189. data/lib/bundles/inspec-compliance/configuration.rb +103 -0
  190. data/lib/bundles/inspec-compliance/http.rb +125 -0
  191. data/lib/bundles/inspec-compliance/images/cc-token.png +0 -0
  192. data/lib/bundles/inspec-compliance/support.rb +36 -0
  193. data/lib/bundles/inspec-compliance/target.rb +106 -0
  194. data/lib/bundles/inspec-compliance/test/integration/default/cli.rb +93 -0
  195. data/lib/bundles/inspec-habitat.rb +12 -0
  196. data/lib/bundles/inspec-habitat/cli.rb +36 -0
  197. data/lib/bundles/inspec-habitat/log.rb +10 -0
  198. data/lib/bundles/inspec-habitat/profile.rb +391 -0
  199. data/lib/bundles/inspec-init.rb +8 -0
  200. data/lib/bundles/inspec-init/README.md +31 -0
  201. data/lib/bundles/inspec-init/cli.rb +97 -0
  202. data/lib/bundles/inspec-init/templates/profile/README.md +3 -0
  203. data/lib/bundles/inspec-init/templates/profile/controls/example.rb +19 -0
  204. data/lib/bundles/inspec-init/templates/profile/inspec.yml +8 -0
  205. data/lib/bundles/inspec-init/templates/profile/libraries/.gitkeep +0 -0
  206. data/lib/bundles/inspec-supermarket.rb +13 -0
  207. data/lib/bundles/inspec-supermarket/README.md +45 -0
  208. data/lib/bundles/inspec-supermarket/api.rb +84 -0
  209. data/lib/bundles/inspec-supermarket/cli.rb +73 -0
  210. data/lib/bundles/inspec-supermarket/target.rb +34 -0
  211. data/lib/fetchers/git.rb +163 -0
  212. data/lib/fetchers/local.rb +74 -0
  213. data/lib/fetchers/mock.rb +35 -0
  214. data/lib/fetchers/url.rb +247 -0
  215. data/lib/inspec.rb +24 -0
  216. data/lib/inspec/archive/tar.rb +29 -0
  217. data/lib/inspec/archive/zip.rb +19 -0
  218. data/lib/inspec/backend.rb +93 -0
  219. data/lib/inspec/base_cli.rb +368 -0
  220. data/lib/inspec/cached_fetcher.rb +66 -0
  221. data/lib/inspec/cli.rb +292 -0
  222. data/lib/inspec/completions/bash.sh.erb +45 -0
  223. data/lib/inspec/completions/fish.sh.erb +34 -0
  224. data/lib/inspec/completions/zsh.sh.erb +61 -0
  225. data/lib/inspec/control_eval_context.rb +179 -0
  226. data/lib/inspec/dependencies/cache.rb +72 -0
  227. data/lib/inspec/dependencies/dependency_set.rb +92 -0
  228. data/lib/inspec/dependencies/lockfile.rb +115 -0
  229. data/lib/inspec/dependencies/requirement.rb +123 -0
  230. data/lib/inspec/dependencies/resolver.rb +86 -0
  231. data/lib/inspec/describe.rb +27 -0
  232. data/lib/inspec/dsl.rb +66 -0
  233. data/lib/inspec/dsl_shared.rb +33 -0
  234. data/lib/inspec/env_printer.rb +157 -0
  235. data/lib/inspec/errors.rb +14 -0
  236. data/lib/inspec/exceptions.rb +12 -0
  237. data/lib/inspec/expect.rb +45 -0
  238. data/lib/inspec/fetcher.rb +45 -0
  239. data/lib/inspec/file_provider.rb +275 -0
  240. data/lib/inspec/formatters.rb +3 -0
  241. data/lib/inspec/formatters/base.rb +259 -0
  242. data/lib/inspec/formatters/json_rspec.rb +20 -0
  243. data/lib/inspec/formatters/show_progress.rb +12 -0
  244. data/lib/inspec/library_eval_context.rb +58 -0
  245. data/lib/inspec/log.rb +11 -0
  246. data/lib/inspec/metadata.rb +247 -0
  247. data/lib/inspec/method_source.rb +24 -0
  248. data/lib/inspec/objects.rb +14 -0
  249. data/lib/inspec/objects/attribute.rb +75 -0
  250. data/lib/inspec/objects/control.rb +61 -0
  251. data/lib/inspec/objects/describe.rb +92 -0
  252. data/lib/inspec/objects/each_loop.rb +36 -0
  253. data/lib/inspec/objects/list.rb +15 -0
  254. data/lib/inspec/objects/or_test.rb +40 -0
  255. data/lib/inspec/objects/ruby_helper.rb +15 -0
  256. data/lib/inspec/objects/tag.rb +27 -0
  257. data/lib/inspec/objects/test.rb +87 -0
  258. data/lib/inspec/objects/value.rb +27 -0
  259. data/lib/inspec/plugins.rb +60 -0
  260. data/lib/inspec/plugins/cli.rb +24 -0
  261. data/lib/inspec/plugins/fetcher.rb +86 -0
  262. data/lib/inspec/plugins/resource.rb +135 -0
  263. data/lib/inspec/plugins/secret.rb +15 -0
  264. data/lib/inspec/plugins/source_reader.rb +40 -0
  265. data/lib/inspec/polyfill.rb +12 -0
  266. data/lib/inspec/profile.rb +513 -0
  267. data/lib/inspec/profile_context.rb +208 -0
  268. data/lib/inspec/profile_vendor.rb +66 -0
  269. data/lib/inspec/reporters.rb +60 -0
  270. data/lib/inspec/reporters/automate.rb +76 -0
  271. data/lib/inspec/reporters/base.rb +25 -0
  272. data/lib/inspec/reporters/cli.rb +356 -0
  273. data/lib/inspec/reporters/json.rb +116 -0
  274. data/lib/inspec/reporters/json_min.rb +48 -0
  275. data/lib/inspec/reporters/junit.rb +78 -0
  276. data/lib/inspec/require_loader.rb +33 -0
  277. data/lib/inspec/resource.rb +190 -0
  278. data/lib/inspec/rule.rb +280 -0
  279. data/lib/inspec/runner.rb +345 -0
  280. data/lib/inspec/runner_mock.rb +41 -0
  281. data/lib/inspec/runner_rspec.rb +175 -0
  282. data/lib/inspec/runtime_profile.rb +26 -0
  283. data/lib/inspec/schema.rb +213 -0
  284. data/lib/inspec/secrets.rb +19 -0
  285. data/lib/inspec/secrets/yaml.rb +30 -0
  286. data/lib/inspec/shell.rb +220 -0
  287. data/lib/inspec/shell_detector.rb +90 -0
  288. data/lib/inspec/source_reader.rb +29 -0
  289. data/lib/inspec/version.rb +8 -0
  290. data/lib/matchers/matchers.rb +339 -0
  291. data/lib/resources/aide_conf.rb +151 -0
  292. data/lib/resources/apache.rb +48 -0
  293. data/lib/resources/apache_conf.rb +149 -0
  294. data/lib/resources/apt.rb +149 -0
  295. data/lib/resources/audit_policy.rb +63 -0
  296. data/lib/resources/auditd.rb +231 -0
  297. data/lib/resources/auditd_conf.rb +46 -0
  298. data/lib/resources/bash.rb +35 -0
  299. data/lib/resources/bond.rb +69 -0
  300. data/lib/resources/bridge.rb +122 -0
  301. data/lib/resources/chocolatey_package.rb +78 -0
  302. data/lib/resources/command.rb +73 -0
  303. data/lib/resources/cpan.rb +58 -0
  304. data/lib/resources/cran.rb +64 -0
  305. data/lib/resources/crontab.rb +169 -0
  306. data/lib/resources/csv.rb +56 -0
  307. data/lib/resources/dh_params.rb +77 -0
  308. data/lib/resources/directory.rb +25 -0
  309. data/lib/resources/docker.rb +236 -0
  310. data/lib/resources/docker_container.rb +89 -0
  311. data/lib/resources/docker_image.rb +83 -0
  312. data/lib/resources/docker_object.rb +57 -0
  313. data/lib/resources/docker_service.rb +90 -0
  314. data/lib/resources/elasticsearch.rb +169 -0
  315. data/lib/resources/etc_fstab.rb +94 -0
  316. data/lib/resources/etc_group.rb +154 -0
  317. data/lib/resources/etc_hosts.rb +66 -0
  318. data/lib/resources/etc_hosts_allow_deny.rb +112 -0
  319. data/lib/resources/file.rb +298 -0
  320. data/lib/resources/filesystem.rb +31 -0
  321. data/lib/resources/firewalld.rb +143 -0
  322. data/lib/resources/gem.rb +70 -0
  323. data/lib/resources/groups.rb +215 -0
  324. data/lib/resources/grub_conf.rb +227 -0
  325. data/lib/resources/host.rb +306 -0
  326. data/lib/resources/http.rb +253 -0
  327. data/lib/resources/iis_app.rb +101 -0
  328. data/lib/resources/iis_site.rb +148 -0
  329. data/lib/resources/inetd_conf.rb +54 -0
  330. data/lib/resources/ini.rb +29 -0
  331. data/lib/resources/interface.rb +129 -0
  332. data/lib/resources/iptables.rb +80 -0
  333. data/lib/resources/json.rb +111 -0
  334. data/lib/resources/kernel_module.rb +107 -0
  335. data/lib/resources/kernel_parameter.rb +58 -0
  336. data/lib/resources/key_rsa.rb +63 -0
  337. data/lib/resources/limits_conf.rb +46 -0
  338. data/lib/resources/login_def.rb +57 -0
  339. data/lib/resources/mount.rb +88 -0
  340. data/lib/resources/mssql_session.rb +101 -0
  341. data/lib/resources/mysql.rb +82 -0
  342. data/lib/resources/mysql_conf.rb +127 -0
  343. data/lib/resources/mysql_session.rb +85 -0
  344. data/lib/resources/nginx.rb +96 -0
  345. data/lib/resources/nginx_conf.rb +226 -0
  346. data/lib/resources/npm.rb +48 -0
  347. data/lib/resources/ntp_conf.rb +51 -0
  348. data/lib/resources/oneget.rb +71 -0
  349. data/lib/resources/oracledb_session.rb +139 -0
  350. data/lib/resources/os.rb +36 -0
  351. data/lib/resources/os_env.rb +86 -0
  352. data/lib/resources/package.rb +370 -0
  353. data/lib/resources/packages.rb +111 -0
  354. data/lib/resources/parse_config.rb +112 -0
  355. data/lib/resources/passwd.rb +76 -0
  356. data/lib/resources/pip.rb +130 -0
  357. data/lib/resources/platform.rb +109 -0
  358. data/lib/resources/port.rb +771 -0
  359. data/lib/resources/postgres.rb +131 -0
  360. data/lib/resources/postgres_conf.rb +114 -0
  361. data/lib/resources/postgres_hba_conf.rb +90 -0
  362. data/lib/resources/postgres_ident_conf.rb +79 -0
  363. data/lib/resources/postgres_session.rb +71 -0
  364. data/lib/resources/powershell.rb +67 -0
  365. data/lib/resources/processes.rb +204 -0
  366. data/lib/resources/rabbitmq_conf.rb +51 -0
  367. data/lib/resources/registry_key.rb +297 -0
  368. data/lib/resources/security_policy.rb +180 -0
  369. data/lib/resources/service.rb +794 -0
  370. data/lib/resources/shadow.rb +159 -0
  371. data/lib/resources/ssh_conf.rb +97 -0
  372. data/lib/resources/ssl.rb +99 -0
  373. data/lib/resources/sys_info.rb +28 -0
  374. data/lib/resources/toml.rb +32 -0
  375. data/lib/resources/users.rb +654 -0
  376. data/lib/resources/vbscript.rb +68 -0
  377. data/lib/resources/virtualization.rb +247 -0
  378. data/lib/resources/windows_feature.rb +84 -0
  379. data/lib/resources/windows_hotfix.rb +35 -0
  380. data/lib/resources/windows_task.rb +102 -0
  381. data/lib/resources/wmi.rb +110 -0
  382. data/lib/resources/x509_certificate.rb +137 -0
  383. data/lib/resources/xinetd.rb +106 -0
  384. data/lib/resources/xml.rb +46 -0
  385. data/lib/resources/yaml.rb +43 -0
  386. data/lib/resources/yum.rb +180 -0
  387. data/lib/resources/zfs_dataset.rb +60 -0
  388. data/lib/resources/zfs_pool.rb +49 -0
  389. data/lib/source_readers/flat.rb +39 -0
  390. data/lib/source_readers/inspec.rb +75 -0
  391. data/lib/utils/command_wrapper.rb +27 -0
  392. data/lib/utils/convert.rb +12 -0
  393. data/lib/utils/database_helpers.rb +77 -0
  394. data/lib/utils/enumerable_delegation.rb +9 -0
  395. data/lib/utils/erlang_parser.rb +192 -0
  396. data/lib/utils/file_reader.rb +25 -0
  397. data/lib/utils/filter.rb +273 -0
  398. data/lib/utils/filter_array.rb +27 -0
  399. data/lib/utils/find_files.rb +47 -0
  400. data/lib/utils/hash.rb +41 -0
  401. data/lib/utils/json_log.rb +18 -0
  402. data/lib/utils/latest_version.rb +22 -0
  403. data/lib/utils/modulator.rb +12 -0
  404. data/lib/utils/nginx_parser.rb +105 -0
  405. data/lib/utils/object_traversal.rb +49 -0
  406. data/lib/utils/parser.rb +274 -0
  407. data/lib/utils/pkey_reader.rb +15 -0
  408. data/lib/utils/plugin_registry.rb +93 -0
  409. data/lib/utils/simpleconfig.rb +120 -0
  410. data/lib/utils/spdx.rb +13 -0
  411. data/lib/utils/spdx.txt +344 -0
  412. metadata +713 -0
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+
3
+ module Inspec::Resources
4
+ class NpmPackage < Inspec.resource(1)
5
+ name 'npm'
6
+ supports platform: 'unix'
7
+ supports platform: 'windows'
8
+ desc 'Use the npm InSpec audit resource to test if a global npm package is installed. npm is the the package manager for Nodejs packages, such as bower and StatsD.'
9
+ example "
10
+ describe npm('bower') do
11
+ it { should be_installed }
12
+ end
13
+ "
14
+
15
+ def initialize(package_name)
16
+ @package_name = package_name
17
+ @cache = nil
18
+ end
19
+
20
+ def info
21
+ return @info if defined?(@info)
22
+
23
+ cmd = inspec.command("npm ls -g --json #{@package_name}")
24
+ @info = {
25
+ name: @package_name,
26
+ type: 'npm',
27
+ installed: cmd.exit_status == 0,
28
+ }
29
+ return @info unless @info[:installed]
30
+
31
+ pkgs = JSON.parse(cmd.stdout)
32
+ @info[:version] = pkgs['dependencies'][@package_name]['version']
33
+ @info
34
+ end
35
+
36
+ def installed?
37
+ info[:installed] == true
38
+ end
39
+
40
+ def version
41
+ info[:version]
42
+ end
43
+
44
+ def to_s
45
+ "Npm Package #{@package_name}"
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+ # copyright: 2015, Vulcano Security GmbH
3
+
4
+ require 'utils/simpleconfig'
5
+ require 'utils/file_reader'
6
+
7
+ module Inspec::Resources
8
+ class NtpConf < Inspec.resource(1)
9
+ name 'ntp_conf'
10
+ supports platform: 'unix'
11
+ desc 'Use the ntp_conf InSpec audit resource to test the synchronization settings defined in the ntp.conf file. This file is typically located at /etc/ntp.conf.'
12
+ example "
13
+ describe ntp_conf do
14
+ its('server') { should_not eq nil }
15
+ its('restrict') { should include '-4 default kod notrap nomodify nopeer noquery'}
16
+ end
17
+ "
18
+
19
+ include FileReader
20
+
21
+ def initialize(path = nil)
22
+ @conf_path = path || '/etc/ntp.conf'
23
+ @content = read_file_content(@conf_path)
24
+ end
25
+
26
+ def method_missing(name)
27
+ param = read_params[name.to_s]
28
+ # extract first value if we have only one value in array
29
+ return param[0] if param.is_a?(Array) and param.length == 1
30
+ param
31
+ end
32
+
33
+ def to_s
34
+ 'ntp.conf'
35
+ end
36
+
37
+ private
38
+
39
+ def read_params
40
+ return @params if defined?(@params)
41
+
42
+ # parse the file
43
+ conf = SimpleConfig.new(
44
+ @content,
45
+ assignment_regex: /^\s*(\S+)\s+(.*)\s*$/,
46
+ multiple_values: true,
47
+ )
48
+ @params = conf.params
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,71 @@
1
+ # encoding: utf-8
2
+
3
+ # This resource talks with OneGet (https://github.com/OneGet/oneget)
4
+ # Its part of Windows Management Framework 5.0 and part of Windows 10
5
+ #
6
+ # Usage:
7
+ # describe oneget('zoomit') do
8
+ # it { should be_installed }
9
+ # end
10
+ module Inspec::Resources
11
+ class OneGetPackage < Inspec.resource(1)
12
+ name 'oneget'
13
+ supports platform: 'windows'
14
+ desc 'Use the oneget InSpec audit resource to test if the named package and/or package version is installed on the system. This resource uses OneGet, which is part of the Windows Management Framework 5.0 and Windows 10. This resource uses the Get-Package cmdlet to return all of the package names in the OneGet repository.'
15
+ example "
16
+ describe oneget('zoomit') do
17
+ it { should be_installed }
18
+ its('version') { should eq '1.2.3' }
19
+ end
20
+ "
21
+
22
+ def initialize(package_name)
23
+ @package_name = package_name
24
+
25
+ # verify that this resource is only supported on Windows
26
+ return skip_resource 'The `oneget` resource is not supported on your OS.' if !inspec.os.windows?
27
+ end
28
+
29
+ def info
30
+ return @info if defined?(@info)
31
+
32
+ @info = {}
33
+ @info[:type] = 'oneget'
34
+ @info[:installed] = false
35
+
36
+ cmd = inspec.command("Get-Package -Name '#{@package_name}' | ConvertTo-Json")
37
+ # cannot rely on exit code for now, successful command returns exit code 1
38
+ # return nil if cmd.exit_status != 0
39
+ # try to parse json
40
+
41
+ begin
42
+ pkgs = JSON.parse(cmd.stdout)
43
+ @info[:installed] = true
44
+
45
+ # sometimes we get multiple values
46
+ if pkgs.is_a?(Array)
47
+ # select the first entry
48
+ pkgs = pkgs.first
49
+ end
50
+ rescue JSON::ParserError => _e
51
+ return @info
52
+ end
53
+
54
+ @info[:name] = pkgs['Name'] if pkgs.key?('Name')
55
+ @info[:version] = pkgs['Version'] if pkgs.key?('Version')
56
+ @info
57
+ end
58
+
59
+ def installed?
60
+ info[:installed] == true
61
+ end
62
+
63
+ def version
64
+ info[:version]
65
+ end
66
+
67
+ def to_s
68
+ "OneGet Package #{@package_name}"
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,139 @@
1
+ # encoding: utf-8
2
+
3
+ require 'hashie/mash'
4
+ require 'utils/database_helpers'
5
+ require 'htmlentities'
6
+ require 'rexml/document'
7
+ require 'csv'
8
+
9
+ module Inspec::Resources
10
+ # STABILITY: Experimental
11
+ # This resource needs further testing and refinement
12
+ #
13
+ class OracledbSession < Inspec.resource(1)
14
+ name 'oracledb_session'
15
+ supports platform: 'unix'
16
+ supports platform: 'windows'
17
+ desc 'Use the oracledb_session InSpec resource to test commands against an Oracle database'
18
+ example "
19
+ sql = oracledb_session(user: 'my_user', pass: 'password')
20
+ describe sql.query(\"SELECT UPPER(VALUE) AS VALUE FROM V$PARAMETER WHERE UPPER(NAME)='AUDIT_SYS_OPERATIONS'\").row(0).column('value') do
21
+ its('value') { should eq 'TRUE' }
22
+ end
23
+ "
24
+
25
+ attr_reader :user, :password, :host, :service
26
+ def initialize(opts = {})
27
+ @user = opts[:user]
28
+ @password = opts[:password] || opts[:pass]
29
+ if opts[:pass]
30
+ warn '[DEPRECATED] use `password` option to supply password instead of `pass`'
31
+ end
32
+
33
+ @host = opts[:host] || 'localhost'
34
+ @port = opts[:port] || '1521'
35
+ @service = opts[:service]
36
+
37
+ # we prefer sqlci although it is way slower than sqlplus, but it understands csv properly
38
+ @sqlcl_bin = 'sql'
39
+ @sqlplus_bin = opts[:sqlplus_bin] || 'sqlplus'
40
+
41
+ return skip_resource "Can't run Oracle checks without authentication" if @user.nil? || @password.nil?
42
+ return skip_resource 'You must provide a service name for the session' if @service.nil?
43
+ end
44
+
45
+ def query(q)
46
+ escaped_query = q.gsub(/\\/, '\\\\').gsub(/"/, '\\"')
47
+ # escape tables with $
48
+ escaped_query = escaped_query.gsub('$', '\\$')
49
+
50
+ p = nil
51
+ # use sqlplus if sqlcl is not available
52
+ if inspec.command(@sqlcl_bin).exist?
53
+ bin = @sqlcl_bin
54
+ opts = "set sqlformat csv\nSET FEEDBACK OFF"
55
+ p = :parse_csv_result
56
+ else
57
+ bin = @sqlplus_bin
58
+ opts = "SET MARKUP HTML ON\nSET FEEDBACK OFF"
59
+ p = :parse_html_result
60
+ end
61
+
62
+ query = verify_query(escaped_query)
63
+ query += ';' unless query.end_with?(';')
64
+ command = %{echo "#{opts}\n#{query}\nEXIT" | #{bin} "#{@user}"/"#{@password}"@#{@host}:#{@port}/#{@service}}
65
+ cmd = inspec.command(command)
66
+
67
+ out = cmd.stdout + "\n" + cmd.stderr
68
+ if out.downcase =~ /^error/
69
+ # TODO: we need to throw an exception here
70
+ # change once https://github.com/chef/inspec/issues/1205 is in
71
+ warn "Could not execute the sql query #{out}"
72
+ DatabaseHelper::SQLQueryResult.new(cmd, Hashie::Mash.new({}))
73
+ end
74
+ DatabaseHelper::SQLQueryResult.new(cmd, send(p, cmd.stdout))
75
+ end
76
+
77
+ def to_s
78
+ 'Oracle Session'
79
+ end
80
+
81
+ private
82
+
83
+ def verify_query(query)
84
+ # ensure we have a ; at the end
85
+ query + ';' if !query.strip.end_with?(';')
86
+ query
87
+ end
88
+
89
+ def parse_csv_result(stdout)
90
+ output = stdout.delete(/\r/)
91
+ table = CSV.parse(output, { headers: true })
92
+
93
+ # convert to hash
94
+ headers = table.headers
95
+
96
+ results = table.map { |row|
97
+ res = {}
98
+ headers.each { |header|
99
+ res[header.downcase] = row[header]
100
+ }
101
+ Hashie::Mash.new(res)
102
+ }
103
+ results
104
+ end
105
+
106
+ def parse_html_result(stdout) # rubocop:disable Metrics/AbcSize
107
+ result = stdout
108
+ # make oracle html valid html by removing the p tag, it does not include a closing tag
109
+ result = result.gsub('<p>', '').gsub('</p>', '').gsub('<br>', '')
110
+ doc = REXML::Document.new result
111
+ table = doc.elements['table']
112
+ hash = []
113
+ if !table.nil?
114
+ rows = table.elements.to_a
115
+ headers = rows[0].elements.to_a('th').map { |entry| entry.text.strip }
116
+ rows.delete_at(0)
117
+
118
+ # iterate over each row, first row is header
119
+ hash = []
120
+ if !rows.nil? && !rows.empty?
121
+ hash = rows.map { |row|
122
+ res = {}
123
+ entries = row.elements.to_a('td')
124
+ # ignore if we have empty entries, oracle is adding th rows in between
125
+ return nil if entries.empty?
126
+ headers.each_with_index { |header, index|
127
+ # we need htmlentities since we do not have nokogiri
128
+ coder = HTMLEntities.new
129
+ val = coder.decode(entries[index].text).strip
130
+ res[header.downcase] = val
131
+ }
132
+ Hashie::Mash.new(res)
133
+ }.compact
134
+ end
135
+ end
136
+ hash
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+
3
+ require 'resources/platform'
4
+
5
+ module Inspec::Resources
6
+ class OSResource < PlatformResource
7
+ name 'os'
8
+ supports platform: 'unix'
9
+ supports platform: 'windows'
10
+ desc 'Use the os InSpec audit resource to test the platform on which the system is running.'
11
+ example "
12
+ describe os[:family] do
13
+ it { should eq 'redhat' }
14
+ end
15
+
16
+ describe os.redhat? do
17
+ it { should eq true }
18
+ end
19
+
20
+ describe os.linux? do
21
+ it { should eq true }
22
+ end
23
+ "
24
+
25
+ # reuse helper methods from backend
26
+ %w{aix? redhat? debian? suse? bsd? solaris? linux? unix? windows? hpux? darwin?}.each do |os_family|
27
+ define_method(os_family.to_sym) do
28
+ @platform.send(os_family)
29
+ end
30
+ end
31
+
32
+ def to_s
33
+ 'Operating System Detection'
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,86 @@
1
+ # encoding: utf-8
2
+ # copyright: 2015, Vulcano Security GmbH
3
+
4
+ # Usage:
5
+ #
6
+ # describe os_env('PATH') do
7
+ # its('split') { should_not include('') }
8
+ # its('split') { should_not include('.') }
9
+ # end
10
+
11
+ require 'utils/simpleconfig'
12
+
13
+ module Inspec::Resources
14
+ class OsEnv < Inspec.resource(1)
15
+ name 'os_env'
16
+ supports platform: 'unix'
17
+ supports platform: 'windows'
18
+ desc 'Use the os_env InSpec audit resource to test the environment variables for the platform on which the system is running.'
19
+ example "
20
+ describe os_env('VARIABLE') do
21
+ its('matcher') { should eq 1 }
22
+ end
23
+ "
24
+
25
+ def initialize(env = nil, target = nil)
26
+ @osenv = env
27
+ @target = unless target.nil?
28
+ if target.casecmp('system') == 0
29
+ 'Machine'
30
+ else
31
+ 'User'
32
+ end
33
+ end
34
+ end
35
+
36
+ def split
37
+ # we can't take advantage of `File::PATH_SEPARATOR` as code is
38
+ # evaluated on the host machine
39
+ path_separator = inspec.os.windows? ? ';' : ':'
40
+ # -1 is required to catch cases like dir1::dir2:
41
+ # where we have a trailing :
42
+ content.nil? ? [] : content.split(path_separator, -1)
43
+ end
44
+
45
+ def content
46
+ return @content if defined?(@content)
47
+ @content = value_for(@osenv, @target) unless @osenv.nil?
48
+ end
49
+
50
+ def to_s
51
+ if @osenv.nil?
52
+ 'Environment variables'
53
+ else
54
+ "Environment variable #{@osenv}"
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def value_for(env, target = nil)
61
+ command = if inspec.os.windows?
62
+ if target.nil?
63
+ "${Env:#{env}}"
64
+ else
65
+ "[System.Environment]::GetEnvironmentVariable('#{env}', [System.EnvironmentVariableTarget]::#{target})"
66
+ end
67
+ else
68
+ 'env'
69
+ end
70
+
71
+ out = inspec.command(command)
72
+
73
+ unless out.exit_status == 0
74
+ skip_resource "Can't read environment variables on #{inspec.os.name}. "\
75
+ "Tried `#{command}` which returned #{out.exit_status}"
76
+ end
77
+
78
+ if inspec.os.windows?
79
+ out.stdout.strip
80
+ else
81
+ params = SimpleConfig.new(out.stdout).params
82
+ params[env]
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,370 @@
1
+ # encoding: utf-8
2
+
3
+ # Resource to determine package information
4
+ #
5
+ # Usage:
6
+ # describe package('nginx') do
7
+ # it { should be_installed }
8
+ # end
9
+ module Inspec::Resources
10
+ class Package < Inspec.resource(1)
11
+ name 'package'
12
+ supports platform: 'unix'
13
+ supports platform: 'windows'
14
+ desc 'Use the package InSpec audit resource to test if the named package and/or package version is installed on the system.'
15
+ example "
16
+ describe package('nginx') do
17
+ it { should be_installed }
18
+ it { should_not be_held } # for dpkg platforms that support holding a version from being upgraded
19
+ its('version') { should eq 1.9.5 }
20
+ end
21
+ "
22
+
23
+ def initialize(package_name, opts = {}) # rubocop:disable Metrics/AbcSize
24
+ @package_name = package_name
25
+ @name = @package_name
26
+ @cache = nil
27
+ # select package manager
28
+ @pkgman = nil
29
+
30
+ os = inspec.os
31
+ if os.debian?
32
+ @pkgman = Deb.new(inspec)
33
+ elsif os.redhat? || %w{suse amazon fedora}.include?(os[:family])
34
+ @pkgman = Rpm.new(inspec, opts)
35
+ elsif ['arch'].include?(os[:name])
36
+ @pkgman = Pacman.new(inspec)
37
+ elsif ['darwin'].include?(os[:family])
38
+ @pkgman = Brew.new(inspec)
39
+ elsif os.windows?
40
+ @pkgman = WindowsPkg.new(inspec)
41
+ elsif ['aix'].include?(os[:family])
42
+ @pkgman = BffPkg.new(inspec)
43
+ elsif os.solaris?
44
+ @pkgman = SolarisPkg.new(inspec)
45
+ elsif ['hpux'].include?(os[:family])
46
+ @pkgman = HpuxPkg.new(inspec)
47
+ else
48
+ raise Inspec::Exceptions::ResourceSkipped, 'The `package` resource is not supported on your OS yet.'
49
+ end
50
+
51
+ evaluate_missing_requirements
52
+ end
53
+
54
+ # returns true if the package is installed
55
+ def installed?(_provider = nil, _version = nil)
56
+ info[:installed] == true
57
+ end
58
+
59
+ # returns true it the package is held (if the OS supports it)
60
+ def held?(_provider = nil, _version = nil)
61
+ info[:held] == true
62
+ end
63
+
64
+ # returns the package description
65
+ def info
66
+ return @cache if !@cache.nil?
67
+ # All `@pkgman.info` methods return `{}`. This matches that
68
+ # behavior if `@pkgman` can't be determined, thus avoiding the
69
+ # `undefined method 'info' for nil:NilClass` error
70
+ return {} if @pkgman.nil?
71
+ @pkgman.info(@package_name)
72
+ end
73
+
74
+ # return the package version
75
+ def version
76
+ info = @pkgman.info(@package_name)
77
+ info[:version]
78
+ end
79
+
80
+ def to_s
81
+ "System Package #{@package_name}"
82
+ end
83
+
84
+ private
85
+
86
+ def evaluate_missing_requirements
87
+ missing_requirements_string = @pkgman.missing_requirements.uniq.join(', ')
88
+ return if missing_requirements_string.empty?
89
+ raise Inspec::Exceptions::ResourceSkipped, "The following requirements are not met for this resource: #{missing_requirements_string}"
90
+ end
91
+ end
92
+
93
+ class PkgManagement
94
+ attr_reader :inspec
95
+ def initialize(inspec)
96
+ @inspec = inspec
97
+ end
98
+
99
+ def missing_requirements
100
+ # Each provider can provide an Array of missing requirements that will be
101
+ # combined into a `ResourceSkipped` exception message.
102
+ []
103
+ end
104
+ end
105
+
106
+ # Debian / Ubuntu
107
+ class Deb < PkgManagement
108
+ def info(package_name)
109
+ cmd = inspec.command("dpkg -s #{package_name}")
110
+ return {} if cmd.exit_status.to_i != 0
111
+
112
+ params = SimpleConfig.new(
113
+ cmd.stdout.chomp,
114
+ assignment_regex: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
115
+ multiple_values: false,
116
+ ).params
117
+ # If the package is installed, Status is "install ok installed"
118
+ # If the package is installed and marked hold, Status is "hold ok installed"
119
+ # If the package is removed and not purged, Status is "deinstall ok config-files" with exit_status 0
120
+ # If the package is purged cmd fails with non-zero exit status
121
+ {
122
+ name: params['Package'],
123
+ installed: params['Status'].split(' ')[2] == 'installed',
124
+ held: params['Status'].split(' ')[0] == 'hold',
125
+ version: params['Version'],
126
+ type: 'deb',
127
+ }
128
+ end
129
+ end
130
+
131
+ # RHEL family
132
+ class Rpm < PkgManagement
133
+ def initialize(inspec, opts)
134
+ super(inspec)
135
+
136
+ @dbpath = opts.fetch(:rpm_dbpath, nil)
137
+ end
138
+
139
+ def missing_requirements
140
+ missing_requirements = []
141
+
142
+ unless @dbpath.nil? || inspec.directory(@dbpath).directory?
143
+ missing_requirements << "RPMDB #{@dbpath} does not exist"
144
+ end
145
+
146
+ missing_requirements
147
+ end
148
+
149
+ def info(package_name)
150
+ rpm_cmd = rpm_command(package_name)
151
+ cmd = inspec.command(rpm_cmd)
152
+ # CentOS does not return an error code if the package is not installed,
153
+ # therefore we need to check for emptyness
154
+ return {} if cmd.exit_status.to_i != 0 || cmd.stdout.chomp.empty?
155
+ params = SimpleConfig.new(
156
+ cmd.stdout.chomp,
157
+ assignment_regex: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
158
+ multiple_values: false,
159
+ ).params
160
+ # On some (all?) systems, the linebreak before the vendor line is missing
161
+ if params['Version'] =~ /\s*Vendor:/
162
+ v = params['Version'].split(' ')[0]
163
+ else
164
+ v = params['Version']
165
+ end
166
+ # On some (all?) systems, the linebreak before the build line is missing
167
+ if params['Release'] =~ /\s*Build Date:/
168
+ r = params['Release'].split(' ')[0]
169
+ else
170
+ r = params['Release']
171
+ end
172
+ {
173
+ name: params['Name'],
174
+ installed: true,
175
+ version: "#{v}-#{r}",
176
+ type: 'rpm',
177
+ }
178
+ end
179
+
180
+ private
181
+
182
+ def rpm_command(package_name)
183
+ cmd = ''
184
+ cmd += 'rpm -qia'
185
+ cmd += " --dbpath #{@dbpath}" if @dbpath
186
+ cmd += ' ' + package_name
187
+
188
+ cmd
189
+ end
190
+ end
191
+
192
+ # MacOS / Darwin implementation
193
+ class Brew < PkgManagement
194
+ def info(package_name)
195
+ brew_path = inspec.command('brew').exist? ? 'brew' : '/usr/local/bin/brew'
196
+ cmd = inspec.command("#{brew_path} info --json=v1 #{package_name}")
197
+
198
+ # If no available formula exists, then `brew` will exit non-zero
199
+ return {} if cmd.exit_status.to_i != 0
200
+
201
+ pkg = JSON.parse(cmd.stdout)[0]
202
+
203
+ # If package exists but is not installed, then `brew` output will not
204
+ # contain `pkg['installed'][0]['version']
205
+ return {} unless pkg.dig('installed', 0, 'version')
206
+
207
+ {
208
+ name: pkg['name'],
209
+ installed: true,
210
+ version: pkg['installed'][0]['version'],
211
+ type: 'brew',
212
+ }
213
+ rescue JSON::ParserError => e
214
+ raise Inspec::Exceptions::ResourceFailed,
215
+ 'Failed to parse JSON from `brew` command. ' \
216
+ "Error: #{e}"
217
+ end
218
+ end
219
+
220
+ # Arch Linux
221
+ class Pacman < PkgManagement
222
+ def info(package_name)
223
+ cmd = inspec.command("pacman -Qi #{package_name}")
224
+ return {} if cmd.exit_status.to_i != 0
225
+
226
+ params = SimpleConfig.new(
227
+ cmd.stdout.chomp,
228
+ assignment_regex: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
229
+ multiple_values: false,
230
+ ).params
231
+
232
+ {
233
+ name: params['Name'],
234
+ installed: true,
235
+ version: params['Version'],
236
+ type: 'pacman',
237
+ }
238
+ end
239
+ end
240
+
241
+ class HpuxPkg < PkgManagement
242
+ def info(package_name)
243
+ cmd = inspec.command("swlist -l product | grep #{package_name}")
244
+ return {} if cmd.exit_status.to_i != 0
245
+ pkg = cmd.stdout.strip.split(' ')
246
+ {
247
+ name: pkg[0],
248
+ installed: true,
249
+ version: pkg[1],
250
+ type: 'pkg',
251
+ }
252
+ end
253
+ end
254
+
255
+ # Determines the installed packages on Windows using the Windows package registry entries.
256
+ # @see: http://blogs.technet.com/b/heyscriptingguy/archive/2013/11/15/use-powershell-to-find-installed-software.aspx
257
+ class WindowsPkg < PkgManagement
258
+ def info(package_name)
259
+ search_paths = [
260
+ 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
261
+ 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
262
+ ]
263
+
264
+ # add 64 bit search paths
265
+ if inspec.os.arch == 'x86_64'
266
+ search_paths << 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
267
+ search_paths << 'HKCU:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
268
+ end
269
+
270
+ # Find the package
271
+ cmd = inspec.command <<-EOF.gsub(/^\s*/, '')
272
+ Get-ItemProperty (@("#{search_paths.join('", "')}") | Where-Object { Test-Path $_ }) |
273
+ Where-Object { $_.DisplayName -like "#{package_name}" -or $_.PSChildName -like "#{package_name}" } |
274
+ Select-Object -Property DisplayName,DisplayVersion | ConvertTo-Json
275
+ EOF
276
+
277
+ # We cannot rely on `exit_status` since PowerShell always exits 0 from the
278
+ # above command. Instead, if no package is found the output of the command
279
+ # will be `''` so we can use that to return `{}` to match the behavior of
280
+ # other package managers.
281
+ return {} if cmd.stdout == ''
282
+
283
+ begin
284
+ package = JSON.parse(cmd.stdout)
285
+ rescue JSON::ParserError => e
286
+ raise Inspec::Exceptions::ResourceFailed,
287
+ 'Failed to parse JSON from PowerShell. ' \
288
+ "Error: #{e}"
289
+ end
290
+
291
+ # What if we match multiple packages? just pick the first one for now.
292
+ package = package[0] if package.is_a?(Array)
293
+
294
+ {
295
+ name: package['DisplayName'],
296
+ installed: true,
297
+ version: package['DisplayVersion'],
298
+ type: 'windows',
299
+ }
300
+ end
301
+ end
302
+
303
+ # AIX
304
+ class BffPkg < PkgManagement
305
+ def info(package_name)
306
+ cmd = inspec.command("lslpp -cL #{package_name}")
307
+ return {} if cmd.exit_status.to_i != 0
308
+
309
+ bff_pkg = cmd.stdout.split("\n").last.split(':')
310
+ {
311
+ name: bff_pkg[1],
312
+ installed: true,
313
+ version: bff_pkg[2],
314
+ type: 'bff',
315
+ }
316
+ end
317
+ end
318
+
319
+ # Solaris
320
+ class SolarisPkg < PkgManagement
321
+ def info(package_name)
322
+ if inspec.os[:release].to_i <= 10
323
+ solaris10_info(package_name)
324
+ else
325
+ solaris11_info(package_name)
326
+ end
327
+ end
328
+
329
+ # solaris 10
330
+ def solaris10_info(package_name)
331
+ cmd = inspec.command("pkginfo -l #{package_name}")
332
+ return {} if cmd.exit_status.to_i != 0
333
+
334
+ params = SimpleConfig.new(
335
+ cmd.stdout.chomp,
336
+ assignment_regex: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
337
+ multiple_values: false,
338
+ ).params
339
+
340
+ # parse 11.10.0,REV=2006.05.18.01.46
341
+ v = params['VERSION'].split(',')
342
+ {
343
+ name: params['PKGINST'],
344
+ installed: true,
345
+ version: v[0] + '-' + v[1].split('=')[1],
346
+ type: 'pkg',
347
+ }
348
+ end
349
+
350
+ # solaris 11
351
+ def solaris11_info(package_name)
352
+ cmd = inspec.command("pkg info #{package_name}")
353
+ return {} if cmd.exit_status.to_i != 0
354
+
355
+ params = SimpleConfig.new(
356
+ cmd.stdout.chomp,
357
+ assignment_regex: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
358
+ multiple_values: false,
359
+ ).params
360
+
361
+ {
362
+ name: params['Name'],
363
+ installed: true,
364
+ # 0.5.11-0.175.3.1.0.5.0
365
+ version: "#{params['Version']}-#{params['Branch']}",
366
+ type: 'pkg',
367
+ }
368
+ end
369
+ end
370
+ end