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,180 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Security Configuration and Analysis
4
+ #
5
+ # Export local security policy:
6
+ # secedit /export /cfg secpol.cfg
7
+ #
8
+ # @link http://www.microsoft.com/en-us/download/details.aspx?id=25250
9
+ #
10
+ # In Windows, some security options are managed differently that the local GPO
11
+ # All local GPO parameters can be examined via Registry, but not all security
12
+ # parameters. Therefore we need a combination of Registry and secedit output
13
+
14
+ require 'hashie'
15
+
16
+ module Inspec::Resources
17
+ # known and supported MS privilege rights
18
+ # @see https://technet.microsoft.com/en-us/library/dd277311.aspx
19
+ # @see https://msdn.microsoft.com/en-us/library/windows/desktop/bb530716(v=vs.85).aspx
20
+ MS_PRIVILEGES_RIGHTS = [
21
+ 'SeNetworkLogonRight',
22
+ 'SeBackupPrivilege',
23
+ 'SeChangeNotifyPrivilege',
24
+ 'SeSystemtimePrivilege',
25
+ 'SeCreatePagefilePrivilege',
26
+ 'SeDebugPrivilege',
27
+ 'SeRemoteShutdownPrivilege',
28
+ 'SeAuditPrivilege',
29
+ 'SeIncreaseQuotaPrivilege',
30
+ 'SeIncreaseBasePriorityPrivilege',
31
+ 'SeLoadDriverPrivilege',
32
+ 'SeBatchLogonRight',
33
+ 'SeServiceLogonRight',
34
+ 'SeInteractiveLogonRight',
35
+ 'SeSecurityPrivilege',
36
+ 'SeSystemEnvironmentPrivilege',
37
+ 'SeProfileSingleProcessPrivilege',
38
+ 'SeSystemProfilePrivilege',
39
+ 'SeAssignPrimaryTokenPrivilege',
40
+ 'SeRestorePrivilege',
41
+ 'SeShutdownPrivilege',
42
+ 'SeTakeOwnershipPrivilege',
43
+ 'SeUndockPrivilege',
44
+ 'SeManageVolumePrivilege',
45
+ 'SeRemoteInteractiveLogonRight',
46
+ 'SeImpersonatePrivilege',
47
+ 'SeCreateGlobalPrivilege',
48
+ 'SeIncreaseWorking',
49
+ 'SeTimeZonePrivilege',
50
+ 'SeCreateSymbolicLinkPrivilege',
51
+ 'SeDenyNetworkLogonRight', # Deny access to this computer from the network
52
+ 'SeDenyInteractiveLogonRight', # Deny logon locally
53
+ 'SeDenyBatchLogonRight', # Deny logon as a batch job
54
+ 'SeDenyServiceLogonRight', # Deny logon as a service
55
+ 'SeTcbPrivilege',
56
+ 'SeMachineAccountPrivilege',
57
+ 'SeCreateTokenPrivilege',
58
+ 'SeCreatePermanentPrivilege',
59
+ 'SeEnableDelegationPrivilege',
60
+ 'SeLockMemoryPrivilege',
61
+ 'SeSyncAgentPrivilege',
62
+ 'SeUnsolicitedInputPrivilege',
63
+ 'SeTrustedCredManAccessPrivilege',
64
+ 'SeRelabelPrivilege', # the privilege to change a Windows integrity label (new to Windows Vista)
65
+ 'SeDenyRemoteInteractiveLogonRight', # Deny logon through Terminal Services
66
+ ].freeze
67
+
68
+ class SecurityPolicy < Inspec.resource(1)
69
+ name 'security_policy'
70
+ supports platform: 'windows'
71
+ desc 'Use the security_policy InSpec audit resource to test security policies on the Microsoft Windows platform.'
72
+ example "
73
+ describe security_policy do
74
+ its('SeNetworkLogonRight') { should include 'S-1-5-11' }
75
+ end
76
+
77
+ describe security_policy(translate_sid: true) do
78
+ its('SeNetworkLogonRight') { should include 'NT AUTHORITY\\Authenticated Users' }
79
+ end
80
+ "
81
+
82
+ def initialize(opts = {})
83
+ @translate_sid = opts[:translate_sid] || false
84
+ end
85
+
86
+ def content
87
+ read_content
88
+ end
89
+
90
+ def params(*opts)
91
+ opts.inject(read_params) do |res, nxt|
92
+ res.respond_to?(:key) ? res[nxt] : nil
93
+ end
94
+ end
95
+
96
+ def method_missing(name)
97
+ params = read_params
98
+ return nil if params.nil?
99
+
100
+ # deep search for hash key
101
+ params.extend Hashie::Extensions::DeepFind
102
+ res = params.deep_find(name.to_s)
103
+
104
+ # return an empty array if configuration does not include rights configuration
105
+ return [] if res.nil? && MS_PRIVILEGES_RIGHTS.include?(name.to_s)
106
+ res
107
+ end
108
+
109
+ def to_s
110
+ 'Security Policy'
111
+ end
112
+
113
+ private
114
+
115
+ def read_content
116
+ return @content if defined?(@content)
117
+
118
+ # using process pid to prevent any race conditions with multiple runners
119
+ export_file = "win_secpol-#{Process.pid}.cfg"
120
+
121
+ # export the security policy
122
+ cmd = inspec.command("secedit /export /cfg #{export_file}")
123
+ return nil if cmd.exit_status.to_i != 0
124
+
125
+ # store file content
126
+ cmd = inspec.command("Get-Content #{export_file}")
127
+ return skip_resource "Can't read security policy" if cmd.exit_status.to_i != 0
128
+
129
+ @content = cmd.stdout
130
+ ensure
131
+ # delete temp file
132
+ inspec.command("Remove-Item #{export_file}").exit_status.to_i
133
+ end
134
+
135
+ def read_params
136
+ return @params if defined?(@params)
137
+ return @params = {} if read_content.nil?
138
+
139
+ conf = SimpleConfig.new(
140
+ @content,
141
+ assignment_regex: /^\s*(.*)=\s*(\S*)\s*$/,
142
+ )
143
+ @params = convert_hash(conf.params)
144
+ end
145
+
146
+ # extracts the values, this methods detects:
147
+ # numbers and SIDs and optimizes them for further usage
148
+ def extract_value(val)
149
+ if val =~ /^\d+$/
150
+ val.to_i
151
+ # special handling for SID array
152
+ elsif val =~ /[,]{0,1}\*\S/
153
+ if @translate_sid
154
+ val.split(',').map { |v|
155
+ object_name = inspec.command("(New-Object System.Security.Principal.SecurityIdentifier(\"#{v.sub('*S', 'S')}\")).Translate( [System.Security.Principal.NTAccount]).Value").stdout.to_s.strip
156
+ object_name.empty? || object_name.nil? ? v.sub('*S', 'S') : object_name
157
+ }
158
+ else
159
+ val.split(',').map { |v|
160
+ v.sub('*S', 'S')
161
+ }
162
+ end
163
+ # special handling for string values with "
164
+ elsif !(m = /^\"(.*)\"$/.match(val)).nil?
165
+ m[1]
166
+ else
167
+ val
168
+ end
169
+ end
170
+
171
+ def convert_hash(hash)
172
+ new_hash = {}
173
+ hash.each do |k, v|
174
+ v.is_a?(Hash) ? value = convert_hash(v) : value = extract_value(v)
175
+ new_hash[k.strip] = value
176
+ end
177
+ new_hash
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,794 @@
1
+ # encoding: utf-8
2
+
3
+ require 'hashie'
4
+ require 'utils/file_reader'
5
+
6
+ module Inspec::Resources
7
+ class Runlevels < Hash
8
+ attr_accessor :owner
9
+
10
+ def self.from_hash(owner, hash = {}, filter = nil)
11
+ res = Runlevels.new(owner)
12
+ filter = filter.first if filter.is_a?(Array) && filter.length <= 1
13
+
14
+ ks = case filter
15
+ when nil
16
+ hash.keys
17
+ when Regexp
18
+ hash.keys.find_all { |x| x.to_s =~ filter }
19
+ when Array
20
+ f = filter.map(&:to_s)
21
+ hash.keys.find_all { |x| f.include?(x.to_s) }
22
+ when Numeric
23
+ hash.keys.include?(filter) ? [filter] : []
24
+ else
25
+ hash.keys.find_all { |x| x == filter }
26
+ end
27
+
28
+ ks.each { |k| res[k] = hash[k] }
29
+ res
30
+ end
31
+
32
+ def initialize(owner, default = false)
33
+ @owner = owner
34
+ super(default)
35
+ end
36
+
37
+ def filter(f)
38
+ Runlevels.from_hash(owner, self, f)
39
+ end
40
+
41
+ # Check if all runlevels are enabled
42
+ #
43
+ # @return [boolean] true if all runlevels are enabled
44
+ def enabled?
45
+ values.all?
46
+ end
47
+
48
+ # Check if all runlevels are disabled
49
+ #
50
+ # @return [boolean] true if all runlevels are disabled
51
+ def disabled?
52
+ values.none?
53
+ end
54
+
55
+ def to_s
56
+ "#{owner} runlevels #{keys.join(', ')}"
57
+ end
58
+ end
59
+
60
+ # We detect the init system for each operating system, based on the operating
61
+ # system.
62
+ #
63
+ # Fedora 15 : systemd
64
+ # RedHat 7 : systemd
65
+ # Ubuntu 15.04 : systemd
66
+ # Ubuntu < 15.04 : upstart
67
+ #
68
+ # TODO: extend the logic to detect the running init system, independently of OS
69
+ class Service < Inspec.resource(1)
70
+ name 'service'
71
+ supports platform: 'unix'
72
+ supports platform: 'windows'
73
+ desc 'Use the service InSpec audit resource to test if the named service is installed, running and/or enabled.'
74
+ example "
75
+ describe service('service_name') do
76
+ it { should be_installed }
77
+ it { should be_enabled }
78
+ it { should be_running }
79
+ its('type') { should be 'systemd' }
80
+ its ('startmode') { should be 'Auto'}
81
+ end
82
+
83
+ describe service('service_name').runlevels(3, 5) do
84
+ it { should be_enabled }
85
+ end
86
+
87
+ describe service('service_name').params do
88
+ its('UnitFileState') { should eq 'enabled' }
89
+ end
90
+ "
91
+
92
+ attr_reader :service_ctl
93
+
94
+ def initialize(service_name, service_ctl = nil)
95
+ @service_name = service_name
96
+ @service_mgmt = nil
97
+ @service_ctl ||= service_ctl
98
+ @cache = nil
99
+ @service_mgmt = select_service_mgmt
100
+
101
+ return skip_resource 'The `service` resource is not supported on your OS yet.' if @service_mgmt.nil?
102
+ end
103
+
104
+ def select_service_mgmt # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
105
+ os = inspec.os
106
+ platform = os[:name]
107
+
108
+ # Ubuntu
109
+ # @see: https://wiki.ubuntu.com/SystemdForUpstartUsers
110
+ # Ubuntu 15.04 : Systemd
111
+ # Systemd runs with PID 1 as /sbin/init.
112
+ # Upstart runs with PID 1 as /sbin/upstart.
113
+ # Ubuntu < 15.04 : Upstart
114
+ # Upstart runs with PID 1 as /sbin/init.
115
+ # Systemd runs with PID 1 as /lib/systemd/systemd.
116
+ if %w{ubuntu}.include?(platform)
117
+ version = os[:release].to_f
118
+ if version < 15.04
119
+ Upstart.new(inspec, service_ctl)
120
+ else
121
+ Systemd.new(inspec, service_ctl)
122
+ end
123
+ elsif %w{linuxmint}.include?(platform)
124
+ version = os[:release].to_f
125
+ if version < 18
126
+ Upstart.new(inspec, service_ctl)
127
+ else
128
+ Systemd.new(inspec, service_ctl)
129
+ end
130
+ elsif %w{debian}.include?(platform)
131
+ version = os[:release].to_i
132
+ if version > 7
133
+ Systemd.new(inspec, service_ctl)
134
+ else
135
+ SysV.new(inspec, service_ctl || '/usr/sbin/service')
136
+ end
137
+ elsif %w{redhat fedora centos oracle}.include?(platform)
138
+ version = os[:release].to_i
139
+ if (%w{redhat centos oracle}.include?(platform) && version >= 7) || (platform == 'fedora' && version >= 15)
140
+ Systemd.new(inspec, service_ctl)
141
+ else
142
+ SysV.new(inspec, service_ctl || '/sbin/service')
143
+ end
144
+ elsif %w{wrlinux}.include?(platform)
145
+ SysV.new(inspec, service_ctl)
146
+ elsif %w{mac_os_x}.include?(platform)
147
+ LaunchCtl.new(inspec, service_ctl)
148
+ elsif os.windows?
149
+ WindowsSrv.new(inspec)
150
+ elsif %w{freebsd}.include?(platform)
151
+ BSDInit.new(inspec, service_ctl)
152
+ elsif %w{arch}.include?(platform)
153
+ Systemd.new(inspec, service_ctl)
154
+ elsif %w{coreos}.include?(platform)
155
+ Systemd.new(inspec, service_ctl)
156
+ elsif %w{suse opensuse}.include?(platform)
157
+ if os[:release].to_i >= 12
158
+ Systemd.new(inspec, service_ctl)
159
+ else
160
+ SysV.new(inspec, service_ctl || '/sbin/service')
161
+ end
162
+ elsif %w{aix}.include?(platform)
163
+ SrcMstr.new(inspec)
164
+ elsif %w{amazon}.include?(platform)
165
+ if os[:release] =~ /^20\d\d/
166
+ Upstart.new(inspec, service_ctl)
167
+ else
168
+ Systemd.new(inspec, service_ctl)
169
+ end
170
+ elsif os.solaris?
171
+ Svcs.new(inspec)
172
+ end
173
+ end
174
+
175
+ def info
176
+ return nil if @service_mgmt.nil?
177
+ @cache ||= @service_mgmt.info(@service_name)
178
+ end
179
+
180
+ # verifies if the service is enabled
181
+ def enabled?(_level = nil)
182
+ return false if info.nil?
183
+ info[:enabled]
184
+ end
185
+
186
+ def params
187
+ return {} if info.nil?
188
+ Hashie::Mash.new(info[:params] || {})
189
+ end
190
+
191
+ # verifies the service is registered
192
+ def installed?(_name = nil, _version = nil)
193
+ return false if info.nil?
194
+ info[:installed]
195
+ end
196
+
197
+ # verifies the service is currently running
198
+ def running?(_under = nil)
199
+ return false if info.nil?
200
+ info[:running]
201
+ end
202
+
203
+ # get all runlevels that are available and their configuration
204
+ def runlevels(*args)
205
+ return Runlevels.new(self) if info.nil? or info[:runlevels].nil?
206
+ Runlevels.from_hash(self, info[:runlevels], args)
207
+ end
208
+
209
+ # returns the service type from info
210
+ def type
211
+ return nil if info.nil?
212
+ info[:type]
213
+ end
214
+
215
+ # returns the service name from info
216
+ def name
217
+ return @service_name if info.nil?
218
+ info[:name]
219
+ end
220
+
221
+ # returns the service description from info
222
+ def description
223
+ return nil if info.nil?
224
+ info[:description]
225
+ end
226
+
227
+ # returns the service start up mode from info
228
+ def startmode
229
+ return nil if info.nil?
230
+ info[:startmode]
231
+ end
232
+
233
+ def to_s
234
+ "Service #{@service_name}"
235
+ end
236
+
237
+ private :info
238
+ end
239
+
240
+ class ServiceManager
241
+ attr_reader :inspec, :service_ctl
242
+ def initialize(inspec, service_ctl = nil)
243
+ @inspec = inspec
244
+ @service_ctl ||= service_ctl
245
+ end
246
+ end
247
+
248
+ # @see: http://www.freedesktop.org/software/systemd/man/systemctl.html
249
+ # @see: http://www.freedesktop.org/software/systemd/man/systemd-system.conf.html
250
+ class Systemd < ServiceManager
251
+ def initialize(inspec, service_ctl = nil)
252
+ @service_ctl = service_ctl || 'systemctl'
253
+ super
254
+ end
255
+
256
+ def is_enabled?(service_name)
257
+ result = inspec.command("#{service_ctl} is-enabled #{service_name} --quiet")
258
+ return true if result.exit_status == 0
259
+
260
+ # Some systems may not have a `.service` file for a particular service
261
+ # which causes the `systemctl is-enabled` check to fail despite the
262
+ # service being enabled. In that event we fallback to `sysv_service`.
263
+ if result.stderr =~ /Failed to get.*No such file or directory/
264
+ return inspec.sysv_service(service_name).enabled?
265
+ end
266
+
267
+ false
268
+ end
269
+
270
+ def is_active?(service_name)
271
+ inspec.command("#{service_ctl} is-active #{service_name} --quiet").exit_status == 0
272
+ end
273
+
274
+ def info(service_name)
275
+ cmd = inspec.command("#{service_ctl} show --all #{service_name}")
276
+ return nil if cmd.exit_status.to_i != 0
277
+
278
+ # parse data
279
+ params = SimpleConfig.new(
280
+ cmd.stdout.chomp,
281
+ assignment_regex: /^\s*([^=]*?)\s*=\s*(.*?)\s*$/,
282
+ multiple_values: false,
283
+ ).params
284
+
285
+ # LoadState values eg. loaded, not-found
286
+ installed = params['LoadState'] == 'loaded'
287
+
288
+ {
289
+ name: params['Id'],
290
+ description: params['Description'],
291
+ installed: installed,
292
+ running: is_active?(service_name),
293
+ enabled: is_enabled?(service_name),
294
+ type: 'systemd',
295
+ params: params,
296
+ }
297
+ end
298
+ end
299
+
300
+ # AIX services
301
+ class SrcMstr < ServiceManager
302
+ attr_reader :name
303
+
304
+ def info(service_name)
305
+ @name = service_name
306
+ running = status?
307
+ return nil if running.nil?
308
+
309
+ {
310
+ name: service_name,
311
+ description: nil,
312
+ installed: true,
313
+ running: running,
314
+ enabled: enabled?,
315
+ type: 'srcmstr',
316
+ }
317
+ end
318
+
319
+ private
320
+
321
+ def status?
322
+ status_cmd = inspec.command("lssrc -s #{@name}")
323
+ return nil if status_cmd.exit_status.to_i != 0
324
+ status_cmd.stdout.split(/\n/).last.chomp =~ /active$/ ? true : false
325
+ end
326
+
327
+ def enabled?
328
+ enabled_rc_tcpip? || enabled_inittab?
329
+ end
330
+
331
+ def enabled_rc_tcpip?
332
+ inspec.command(
333
+ "grep -v ^# /etc/rc.tcpip | grep 'start ' | grep -Eq '(/{0,1}| )#{name} '",
334
+ ).exit_status == 0
335
+ end
336
+
337
+ def enabled_inittab?
338
+ inspec.command("lsitab #{name}").exit_status == 0
339
+ end
340
+ end
341
+
342
+ # @see: http://upstart.ubuntu.com
343
+ class Upstart < ServiceManager
344
+ include FileReader
345
+
346
+ def initialize(service_name, service_ctl = nil)
347
+ @service_ctl = service_ctl || 'initctl'
348
+ super
349
+ end
350
+
351
+ def info(service_name)
352
+ # get the status of upstart service
353
+ status = inspec.command("#{service_ctl} status #{service_name}")
354
+
355
+ # fallback for systemv services, those are not handled via `initctl`
356
+ return SysV.new(inspec).info(service_name) if status.exit_status.to_i != 0 || status.stdout == ''
357
+
358
+ # @see: http://upstart.ubuntu.com/cookbook/#job-states
359
+ # grep for running to indicate the service is there
360
+ running = !status.stdout[%r{start/running}].nil?
361
+ enabled = info_enabled(service_name)
362
+
363
+ {
364
+ name: service_name,
365
+ description: nil,
366
+ installed: true,
367
+ running: running,
368
+ enabled: enabled,
369
+ type: 'upstart',
370
+ }
371
+ end
372
+
373
+ private
374
+
375
+ def info_enabled(service_name)
376
+ # check if a service is enabled
377
+ config = read_file_content("/etc/init/#{service_name}.conf", allow_empty: true)
378
+
379
+ !config.match(/^\s*start on/).nil?
380
+ end
381
+
382
+ def version
383
+ @version ||= begin
384
+ out = inspec.command("#{service_ctl} --version").stdout
385
+ Gem::Version.new(out[/\(upstart ([^\)]+)\)/, 1])
386
+ end
387
+ end
388
+ end
389
+
390
+ class SysV < ServiceManager
391
+ RUNLEVELS = { 0=>false, 1=>false, 2=>false, 3=>false, 4=>false, 5=>false, 6=>false }.freeze
392
+
393
+ def initialize(service_name, service_ctl = nil)
394
+ @service_ctl = service_ctl || 'service'
395
+ super
396
+ end
397
+
398
+ def info(service_name)
399
+ # check if service is installed
400
+ # read all available services via ls /etc/init.d/
401
+ srvlist = inspec.command('ls -1 /etc/init.d/')
402
+ return nil if srvlist.exit_status != 0
403
+
404
+ # check if the service is in list
405
+ service = srvlist.stdout.split("\n").select { |srv| srv == service_name }
406
+
407
+ # abort if we could not find any service
408
+ return nil if service.empty?
409
+
410
+ # read all enabled services from runlevel
411
+ # on rhel via: 'chkconfig --list', is not installed by default
412
+ # bash: for i in `find /etc/rc*.d -name S*`; do basename $i | sed -r 's/^S[0-9]+//'; done | sort | uniq
413
+ enabled_services_cmd = inspec.command('find /etc/rc*.d /etc/init.d/rc*.d -name "S*"').stdout
414
+ service_line = %r{rc(?<runlevel>[0-6])\.d/S[^/]*?#{Regexp.escape service_name}$}
415
+ all_services = enabled_services_cmd.split("\n").map { |line|
416
+ service_line.match(line)
417
+ }.compact
418
+ enabled = !all_services.empty?
419
+
420
+ # Determine a list of runlevels which this service is activated for
421
+ runlevels = RUNLEVELS.dup
422
+ all_services.each { |x| runlevels[x[:runlevel].to_i] = true }
423
+
424
+ # check if service is really running
425
+ # service throws an exit code if the service is not installed or
426
+ # not enabled
427
+
428
+ cmd = inspec.command("#{service_ctl} #{service_name} status")
429
+ running = cmd.exit_status == 0
430
+ {
431
+ name: service_name,
432
+ description: nil,
433
+ installed: true,
434
+ running: running,
435
+ enabled: enabled,
436
+ runlevels: runlevels,
437
+ type: 'sysv',
438
+ }
439
+ end
440
+ end
441
+
442
+ # @see: https://www.freebsd.org/doc/en/articles/linux-users/startup.html
443
+ # @see: https://www.freebsd.org/cgi/man.cgi?query=rc.conf&sektion=5
444
+ class BSDInit < ServiceManager
445
+ def initialize(service_name, service_ctl = nil)
446
+ @service_ctl = service_ctl || 'service'
447
+ super
448
+ end
449
+
450
+ def info(service_name)
451
+ # check if service is enabled
452
+ # services are enabled in /etc/rc.conf and /etc/defaults/rc.conf
453
+ # via #{service_name}_enable="YES"
454
+ # service SERVICE status returns the following result if not activated:
455
+ # Cannot 'status' sshd. Set sshd_enable to YES in /etc/rc.conf or use 'onestatus' instead of 'status'.
456
+ # gather all enabled services
457
+ cmd = inspec.command("#{service_ctl} -e")
458
+ return nil if cmd.exit_status != 0
459
+
460
+ # search for the service
461
+ srv = /(^.*#{service_name}$)/.match(cmd.stdout)
462
+ return nil if srv.nil? || srv[0].nil?
463
+ enabled = true
464
+
465
+ # check if the service is running
466
+ # if the service is not available or not running, we always get an error code
467
+ cmd = inspec.command("#{service_ctl} #{service_name} onestatus")
468
+ running = cmd.exit_status == 0
469
+
470
+ {
471
+ name: service_name,
472
+ description: nil,
473
+ installed: true,
474
+ running: running,
475
+ enabled: enabled,
476
+ type: 'bsd-init',
477
+ }
478
+ end
479
+ end
480
+
481
+ class Runit < ServiceManager
482
+ def initialize(service_name, service_ctl = nil)
483
+ @service_ctl = service_ctl || 'sv'
484
+ super
485
+ end
486
+
487
+ # rubocop:disable Style/DoubleNegation
488
+ def info(service_name)
489
+ # get the status of runit service
490
+ cmd = inspec.command("#{service_ctl} status #{service_name}")
491
+ # return nil unless cmd.exit_status == 0 # NOTE(sr) why do we do this?
492
+
493
+ installed = cmd.exit_status == 0
494
+ running = installed && !!(cmd.stdout =~ /^run:/)
495
+ enabled = installed && (running || !!(cmd.stdout =~ /normally up/) || !!(cmd.stdout =~ /want up/))
496
+
497
+ {
498
+ name: service_name,
499
+ description: nil,
500
+ installed: installed,
501
+ running: running,
502
+ enabled: enabled,
503
+ type: 'runit',
504
+ }
505
+ end
506
+ end
507
+
508
+ # MacOS / Darwin
509
+ # new launctl on macos 10.10
510
+ class LaunchCtl < ServiceManager
511
+ def initialize(service_name, service_ctl = nil)
512
+ @service_ctl = service_ctl || 'launchctl'
513
+ super
514
+ end
515
+
516
+ def info(service_name)
517
+ # get the status of upstart service
518
+ cmd = inspec.command("#{service_ctl} list")
519
+ return nil if cmd.exit_status != 0
520
+
521
+ # search for the service
522
+ srv = /(^.*#{service_name}.*)/.match(cmd.stdout)
523
+ return nil if srv.nil? || srv[0].nil?
524
+
525
+ # extract values from service
526
+ parsed_srv = /^(?<pid>[0-9-]+)\t(?<exit>[0-9]+)\t(?<name>\S*)$/.match(srv[0])
527
+ enabled = !parsed_srv['name'].nil? # it's in the list
528
+
529
+ # check if the service is running
530
+ pid = parsed_srv['pid']
531
+ running = pid != '-'
532
+
533
+ # extract service label
534
+ srv = parsed_srv['name'] || service_name
535
+
536
+ {
537
+ name: srv,
538
+ description: nil,
539
+ installed: true,
540
+ running: running,
541
+ enabled: enabled,
542
+ type: 'darwin',
543
+ }
544
+ end
545
+ end
546
+
547
+ # Determine the service state from Windows
548
+ # Uses Powershell to retrieve the information
549
+ class WindowsSrv < ServiceManager
550
+ # Determine service details
551
+ # PS: Get-Service -Name 'dhcp'| Select-Object -Property Name, DisplayName, Status | ConvertTo-Json
552
+ # {
553
+ # "Name": "dhcp",
554
+ # "DisplayName": "DHCP Client",
555
+ # "Status": 4
556
+ # }
557
+ #
558
+ # Until StartMode is not added to Get-Service, we need to do a workaround
559
+ # @see: https://connect.microsoft.com/PowerShell/feedback/details/424948/i-would-like-to-see-the-property-starttype-added-to-get-services
560
+ # Also see: https://msdn.microsoft.com/en-us/library/aa384896(v=vs.85).aspx
561
+ # Use the following powershell to determine the start mode
562
+ # PS: Get-WmiObject -Class Win32_Service | Where-Object {$_.Name -eq $name -or $_.DisplayName -eq $name} | Select-Object -Prop
563
+ # erty Name, StartMode, State, Status | ConvertTo-Json
564
+ # {
565
+ # "Name": "Dhcp",
566
+ # "StartMode": "Auto",
567
+ # "State": "Running",
568
+ # "Status": "OK"
569
+ # }
570
+ #
571
+ # Windows Services have the following status code:
572
+ # @see: https://msdn.microsoft.com/en-us/library/windows/desktop/ms685996(v=vs.85).aspx
573
+ # - 1: Stopped
574
+ # - 2: Starting
575
+ # - 3: Stopping
576
+ # - 4: Running
577
+ # - 5: Continue Pending
578
+ # - 6: Pause Pending
579
+ # - 7: Paused
580
+ def info(service_name)
581
+ cmd = inspec.command("New-Object -Type PSObject | Add-Member -MemberType NoteProperty -Name Service -Value (Get-Service -Name '#{service_name}'| Select-Object -Property Name, DisplayName, Status) -PassThru | Add-Member -MemberType NoteProperty -Name WMI -Value (Get-WmiObject -Class Win32_Service | Where-Object {$_.Name -eq '#{service_name}' -or $_.DisplayName -eq '#{service_name}'} | Select-Object -Property StartMode) -PassThru | ConvertTo-Json")
582
+
583
+ # cannot rely on exit code for now, successful command returns exit code 1
584
+ # return nil if cmd.exit_status != 0
585
+ # try to parse json
586
+ begin
587
+ service = JSON.parse(cmd.stdout)
588
+ rescue JSON::ParserError => _e
589
+ return nil
590
+ end
591
+
592
+ # check that we got a response
593
+ return nil if service.nil? || service['Service'].nil?
594
+
595
+ {
596
+ name: service['Service']['Name'],
597
+ description: service['Service']['DisplayName'],
598
+ installed: true,
599
+ running: service_running?(service),
600
+ enabled: service_enabled?(service),
601
+ startmode: service['WMI']['StartMode'],
602
+ type: 'windows',
603
+ }
604
+ end
605
+
606
+ private
607
+
608
+ # detect if service is enabled
609
+ def service_enabled?(service)
610
+ !service['WMI'].nil? &&
611
+ !service['WMI']['StartMode'].nil? &&
612
+ (service['WMI']['StartMode'] == 'Auto' ||
613
+ service['WMI']['StartMode'] == 'Manual')
614
+ end
615
+
616
+ # detect if service is running
617
+ def service_running?(service)
618
+ !service['Service']['Status'].nil? && service['Service']['Status'] == 4
619
+ end
620
+ end
621
+
622
+ # Solaris services
623
+ class Svcs < ServiceManager
624
+ def initialize(service_name, service_ctl = nil)
625
+ @service_ctl = service_ctl || 'svcs'
626
+ super
627
+ end
628
+
629
+ def info(service_name)
630
+ # get the status of runit service
631
+ cmd = inspec.command("#{service_ctl} -l #{service_name}")
632
+ return nil if cmd.exit_status != 0
633
+
634
+ params = SimpleConfig.new(
635
+ cmd.stdout.chomp,
636
+ assignment_regex: /^(\w+)\s*(.*)$/,
637
+ multiple_values: false,
638
+ ).params
639
+
640
+ installed = cmd.exit_status == 0
641
+ running = installed && (params['state'] == 'online')
642
+ enabled = installed && (params['enabled'] == 'true')
643
+
644
+ {
645
+ name: service_name,
646
+ description: params['name'],
647
+ installed: installed,
648
+ running: running,
649
+ enabled: enabled,
650
+ type: 'svcs',
651
+ }
652
+ end
653
+ end
654
+
655
+ # specific resources for specific service managers
656
+
657
+ class SystemdService < Service
658
+ name 'systemd_service'
659
+ supports platform: 'unix'
660
+ desc 'Use the systemd_service InSpec audit resource to test if the named service (controlled by systemd) is installed, running and/or enabled.'
661
+ example "
662
+ # to override service mgmt auto-detection
663
+ describe systemd_service('service_name') do
664
+ it { should be_installed }
665
+ it { should be_enabled }
666
+ it { should be_running }
667
+ end
668
+
669
+ # to set a non-standard systemctl path
670
+ describe systemd_service('service_name', '/path/to/systemctl') do
671
+ it { should be_running }
672
+ end
673
+ "
674
+
675
+ def select_service_mgmt
676
+ Systemd.new(inspec, service_ctl)
677
+ end
678
+ end
679
+
680
+ class UpstartService < Service
681
+ name 'upstart_service'
682
+ supports platform: 'unix'
683
+ desc 'Use the upstart_service InSpec audit resource to test if the named service (controlled by upstart) is installed, running and/or enabled.'
684
+ example "
685
+ # to override service mgmt auto-detection
686
+ describe upstart_service('service_name') do
687
+ it { should be_installed }
688
+ it { should be_enabled }
689
+ it { should be_running }
690
+ end
691
+
692
+ # to set a non-standard initctl path
693
+ describe upstart_service('service_name', '/path/to/initctl') do
694
+ it { should be_running }
695
+ end
696
+ "
697
+
698
+ def select_service_mgmt
699
+ Upstart.new(inspec, service_ctl)
700
+ end
701
+ end
702
+
703
+ class SysVService < Service
704
+ name 'sysv_service'
705
+ supports platform: 'unix'
706
+ desc 'Use the sysv_service InSpec audit resource to test if the named service (controlled by SysV) is installed, running and/or enabled.'
707
+ example "
708
+ # to override service mgmt auto-detection
709
+ describe sysv_service('service_name') do
710
+ it { should be_installed }
711
+ it { should be_enabled }
712
+ it { should be_running }
713
+ end
714
+
715
+ # to set a non-standard service path
716
+ describe sysv_service('service_name', '/path/to/service') do
717
+ it { should be_running }
718
+ end
719
+ "
720
+
721
+ def select_service_mgmt
722
+ SysV.new(inspec, service_ctl)
723
+ end
724
+ end
725
+
726
+ class BSDService < Service
727
+ name 'bsd_service'
728
+ supports platform: 'unix'
729
+ desc 'Use the bsd_service InSpec audit resource to test if the named service (controlled by BSD init) is installed, running and/or enabled.'
730
+ example "
731
+ # to override service mgmt auto-detection
732
+ describe bsd_service('service_name') do
733
+ it { should be_installed }
734
+ it { should be_enabled }
735
+ it { should be_running }
736
+ end
737
+
738
+ # to set a non-standard service path
739
+ describe bsd_service('service_name', '/path/to/service') do
740
+ it { should be_running }
741
+ end
742
+ "
743
+
744
+ def select_service_mgmt
745
+ BSDInit.new(inspec, service_ctl)
746
+ end
747
+ end
748
+
749
+ class LaunchdService < Service
750
+ name 'launchd_service'
751
+ supports platform: 'unix'
752
+ desc 'Use the launchd_service InSpec audit resource to test if the named service (controlled by launchd) is installed, running and/or enabled.'
753
+ example "
754
+ # to override service mgmt auto-detection
755
+ describe launchd_service('service_name') do
756
+ it { should be_installed }
757
+ it { should be_enabled }
758
+ it { should be_running }
759
+ end
760
+
761
+ # to set a non-standard launchctl path
762
+ describe launchd_service('service_name', '/path/to/launchctl') do
763
+ it { should be_running }
764
+ end
765
+ "
766
+
767
+ def select_service_mgmt
768
+ LaunchCtl.new(inspec, service_ctl)
769
+ end
770
+ end
771
+
772
+ class RunitService < Service
773
+ name 'runit_service'
774
+ supports platform: 'unix'
775
+ desc 'Use the runit_service InSpec audit resource to test if the named service (controlled by runit) is installed, running and/or enabled.'
776
+ example "
777
+ # to override service mgmt auto-detection
778
+ describe runit_service('service_name') do
779
+ it { should be_installed }
780
+ it { should be_enabled }
781
+ it { should be_running }
782
+ end
783
+
784
+ # to set a non-standard sv path
785
+ describe runit_service('service_name', '/path/to/sv') do
786
+ it { should be_running }
787
+ end
788
+ "
789
+
790
+ def select_service_mgmt
791
+ Runit.new(inspec, service_ctl)
792
+ end
793
+ end
794
+ end