inspec 2.1.0 → 2.1.10

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 (489) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +101 -101
  3. data/CHANGELOG.md +3024 -3004
  4. data/Gemfile +55 -55
  5. data/LICENSE +14 -14
  6. data/MAINTAINERS.md +33 -33
  7. data/MAINTAINERS.toml +52 -52
  8. data/README.md +447 -446
  9. data/Rakefile +322 -322
  10. data/bin/inspec +12 -12
  11. data/docs/.gitignore +2 -2
  12. data/docs/README.md +40 -40
  13. data/docs/dsl_inspec.md +258 -258
  14. data/docs/dsl_resource.md +100 -93
  15. data/docs/glossary.md +99 -99
  16. data/docs/habitat.md +191 -191
  17. data/docs/inspec_and_friends.md +114 -114
  18. data/docs/matchers.md +169 -169
  19. data/docs/migration.md +293 -293
  20. data/docs/platforms.md +118 -118
  21. data/docs/plugin_kitchen_inspec.md +50 -50
  22. data/docs/profiles.md +376 -376
  23. data/docs/reporters.md +105 -105
  24. data/docs/resources/aide_conf.md.erb +75 -75
  25. data/docs/resources/apache.md.erb +67 -67
  26. data/docs/resources/apache_conf.md.erb +68 -68
  27. data/docs/resources/apt.md.erb +71 -71
  28. data/docs/resources/audit_policy.md.erb +47 -47
  29. data/docs/resources/auditd.md.erb +79 -79
  30. data/docs/resources/auditd_conf.md.erb +68 -68
  31. data/docs/resources/aws_cloudtrail_trail.md.erb +140 -140
  32. data/docs/resources/aws_cloudtrail_trails.md.erb +81 -81
  33. data/docs/resources/aws_cloudwatch_alarm.md.erb +86 -86
  34. data/docs/resources/aws_cloudwatch_log_metric_filter.md.erb +151 -151
  35. data/docs/resources/aws_config_recorder.md.erb +71 -71
  36. data/docs/resources/aws_ec2_instance.md.erb +106 -106
  37. data/docs/resources/aws_iam_access_key.md.erb +123 -123
  38. data/docs/resources/aws_iam_access_keys.md.erb +198 -198
  39. data/docs/resources/aws_iam_group.md.erb +46 -46
  40. data/docs/resources/aws_iam_groups.md.erb +43 -43
  41. data/docs/resources/aws_iam_password_policy.md.erb +76 -76
  42. data/docs/resources/aws_iam_policies.md.erb +82 -82
  43. data/docs/resources/aws_iam_policy.md.erb +144 -144
  44. data/docs/resources/aws_iam_role.md.erb +63 -63
  45. data/docs/resources/aws_iam_root_user.md.erb +58 -58
  46. data/docs/resources/aws_iam_user.md.erb +64 -64
  47. data/docs/resources/aws_iam_users.md.erb +89 -89
  48. data/docs/resources/aws_kms_keys.md.erb +84 -84
  49. data/docs/resources/aws_route_table.md.erb +47 -47
  50. data/docs/resources/aws_s3_bucket.md.erb +134 -134
  51. data/docs/resources/aws_s3_bucket_object.md.erb +83 -0
  52. data/docs/resources/aws_security_group.md.erb +151 -151
  53. data/docs/resources/aws_security_groups.md.erb +91 -91
  54. data/docs/resources/aws_sns_subscription.md.erb +125 -0
  55. data/docs/resources/aws_sns_topic.md.erb +63 -63
  56. data/docs/resources/aws_sns_topics.md.erb +52 -0
  57. data/docs/resources/aws_subnet.md.erb +134 -134
  58. data/docs/resources/aws_subnets.md.erb +126 -126
  59. data/docs/resources/aws_vpc.md.erb +120 -120
  60. data/docs/resources/aws_vpcs.md.erb +48 -48
  61. data/docs/resources/azure_generic_resource.md.erb +171 -171
  62. data/docs/resources/azure_resource_group.md.erb +284 -284
  63. data/docs/resources/azure_virtual_machine.md.erb +347 -347
  64. data/docs/resources/azure_virtual_machine_data_disk.md.erb +224 -224
  65. data/docs/resources/bash.md.erb +75 -75
  66. data/docs/resources/bond.md.erb +90 -90
  67. data/docs/resources/bridge.md.erb +57 -57
  68. data/docs/resources/bsd_service.md.erb +67 -67
  69. data/docs/resources/command.md.erb +138 -138
  70. data/docs/resources/cpan.md.erb +79 -79
  71. data/docs/resources/cran.md.erb +64 -64
  72. data/docs/resources/crontab.md.erb +89 -89
  73. data/docs/resources/csv.md.erb +54 -54
  74. data/docs/resources/dh_params.md.erb +205 -205
  75. data/docs/resources/directory.md.erb +30 -30
  76. data/docs/resources/docker.md.erb +219 -219
  77. data/docs/resources/docker_container.md.erb +103 -103
  78. data/docs/resources/docker_image.md.erb +94 -94
  79. data/docs/resources/docker_service.md.erb +114 -114
  80. data/docs/resources/elasticsearch.md.erb +242 -242
  81. data/docs/resources/etc_fstab.md.erb +125 -125
  82. data/docs/resources/etc_group.md.erb +75 -75
  83. data/docs/resources/etc_hosts.md.erb +78 -78
  84. data/docs/resources/etc_hosts_allow.md.erb +74 -74
  85. data/docs/resources/etc_hosts_deny.md.erb +74 -74
  86. data/docs/resources/file.md.erb +526 -526
  87. data/docs/resources/filesystem.md.erb +41 -41
  88. data/docs/resources/firewalld.md.erb +107 -107
  89. data/docs/resources/gem.md.erb +79 -79
  90. data/docs/resources/group.md.erb +61 -61
  91. data/docs/resources/grub_conf.md.erb +101 -101
  92. data/docs/resources/host.md.erb +86 -86
  93. data/docs/resources/http.md.erb +196 -196
  94. data/docs/resources/iis_app.md.erb +122 -122
  95. data/docs/resources/iis_site.md.erb +135 -135
  96. data/docs/resources/inetd_conf.md.erb +94 -94
  97. data/docs/resources/ini.md.erb +76 -76
  98. data/docs/resources/interface.md.erb +58 -58
  99. data/docs/resources/iptables.md.erb +64 -64
  100. data/docs/resources/json.md.erb +63 -63
  101. data/docs/resources/kernel_module.md.erb +120 -120
  102. data/docs/resources/kernel_parameter.md.erb +53 -53
  103. data/docs/resources/key_rsa.md.erb +85 -85
  104. data/docs/resources/launchd_service.md.erb +57 -57
  105. data/docs/resources/limits_conf.md.erb +75 -75
  106. data/docs/resources/{login_def.md.erb → login_defs.md.erb} +71 -71
  107. data/docs/resources/mount.md.erb +69 -69
  108. data/docs/resources/mssql_session.md.erb +60 -60
  109. data/docs/resources/mysql_conf.md.erb +99 -99
  110. data/docs/resources/mysql_session.md.erb +74 -74
  111. data/docs/resources/nginx.md.erb +79 -79
  112. data/docs/resources/nginx_conf.md.erb +138 -128
  113. data/docs/resources/npm.md.erb +60 -60
  114. data/docs/resources/ntp_conf.md.erb +60 -60
  115. data/docs/resources/oneget.md.erb +53 -53
  116. data/docs/resources/oracledb_session.md.erb +52 -52
  117. data/docs/resources/os.md.erb +141 -141
  118. data/docs/resources/os_env.md.erb +78 -78
  119. data/docs/resources/package.md.erb +120 -120
  120. data/docs/resources/packages.md.erb +67 -67
  121. data/docs/resources/parse_config.md.erb +103 -103
  122. data/docs/resources/parse_config_file.md.erb +138 -138
  123. data/docs/resources/passwd.md.erb +141 -141
  124. data/docs/resources/pip.md.erb +67 -67
  125. data/docs/resources/port.md.erb +137 -137
  126. data/docs/resources/postgres_conf.md.erb +79 -79
  127. data/docs/resources/postgres_hba_conf.md.erb +93 -93
  128. data/docs/resources/postgres_ident_conf.md.erb +76 -76
  129. data/docs/resources/postgres_session.md.erb +69 -69
  130. data/docs/resources/powershell.md.erb +102 -102
  131. data/docs/resources/processes.md.erb +109 -109
  132. data/docs/resources/rabbitmq_config.md.erb +41 -41
  133. data/docs/resources/registry_key.md.erb +158 -158
  134. data/docs/resources/runit_service.md.erb +57 -57
  135. data/docs/resources/security_policy.md.erb +47 -47
  136. data/docs/resources/service.md.erb +121 -121
  137. data/docs/resources/shadow.md.erb +146 -146
  138. data/docs/resources/ssh_config.md.erb +73 -80
  139. data/docs/resources/sshd_config.md.erb +83 -83
  140. data/docs/resources/ssl.md.erb +119 -119
  141. data/docs/resources/sys_info.md.erb +42 -42
  142. data/docs/resources/systemd_service.md.erb +57 -57
  143. data/docs/resources/sysv_service.md.erb +57 -57
  144. data/docs/resources/upstart_service.md.erb +57 -57
  145. data/docs/resources/user.md.erb +140 -140
  146. data/docs/resources/users.md.erb +127 -127
  147. data/docs/resources/vbscript.md.erb +55 -55
  148. data/docs/resources/virtualization.md.erb +57 -57
  149. data/docs/resources/windows_feature.md.erb +47 -47
  150. data/docs/resources/windows_hotfix.md.erb +53 -53
  151. data/docs/resources/windows_task.md.erb +95 -95
  152. data/docs/resources/wmi.md.erb +81 -81
  153. data/docs/resources/x509_certificate.md.erb +151 -151
  154. data/docs/resources/xinetd_conf.md.erb +156 -156
  155. data/docs/resources/xml.md.erb +85 -85
  156. data/docs/resources/yaml.md.erb +69 -69
  157. data/docs/resources/yum.md.erb +98 -98
  158. data/docs/resources/zfs_dataset.md.erb +53 -53
  159. data/docs/resources/zfs_pool.md.erb +47 -47
  160. data/docs/ruby_usage.md +203 -203
  161. data/docs/shared/matcher_be.md.erb +1 -1
  162. data/docs/shared/matcher_cmp.md.erb +43 -43
  163. data/docs/shared/matcher_eq.md.erb +3 -3
  164. data/docs/shared/matcher_include.md.erb +1 -1
  165. data/docs/shared/matcher_match.md.erb +1 -1
  166. data/docs/shell.md +217 -217
  167. data/examples/README.md +8 -8
  168. data/examples/inheritance/README.md +65 -65
  169. data/examples/inheritance/controls/example.rb +14 -14
  170. data/examples/inheritance/inspec.yml +15 -15
  171. data/examples/kitchen-ansible/.kitchen.yml +25 -25
  172. data/examples/kitchen-ansible/Gemfile +19 -19
  173. data/examples/kitchen-ansible/README.md +53 -53
  174. data/examples/kitchen-ansible/files/nginx.repo +6 -6
  175. data/examples/kitchen-ansible/tasks/main.yml +16 -16
  176. data/examples/kitchen-ansible/test/integration/default/default.yml +5 -5
  177. data/examples/kitchen-ansible/test/integration/default/web_spec.rb +28 -28
  178. data/examples/kitchen-chef/.kitchen.yml +20 -20
  179. data/examples/kitchen-chef/Berksfile +3 -3
  180. data/examples/kitchen-chef/Gemfile +19 -19
  181. data/examples/kitchen-chef/README.md +27 -27
  182. data/examples/kitchen-chef/metadata.rb +7 -7
  183. data/examples/kitchen-chef/recipes/default.rb +6 -6
  184. data/examples/kitchen-chef/recipes/nginx.rb +30 -30
  185. data/examples/kitchen-chef/test/integration/default/web_spec.rb +28 -28
  186. data/examples/kitchen-puppet/.kitchen.yml +22 -22
  187. data/examples/kitchen-puppet/Gemfile +20 -20
  188. data/examples/kitchen-puppet/Puppetfile +25 -25
  189. data/examples/kitchen-puppet/README.md +53 -53
  190. data/examples/kitchen-puppet/manifests/site.pp +33 -33
  191. data/examples/kitchen-puppet/metadata.json +11 -11
  192. data/examples/kitchen-puppet/test/integration/default/web_spec.rb +28 -28
  193. data/examples/meta-profile/README.md +37 -37
  194. data/examples/meta-profile/controls/example.rb +13 -13
  195. data/examples/meta-profile/inspec.yml +13 -13
  196. data/examples/profile-attribute.yml +2 -2
  197. data/examples/profile-attribute/README.md +14 -14
  198. data/examples/profile-attribute/controls/example.rb +11 -11
  199. data/examples/profile-attribute/inspec.yml +8 -8
  200. data/examples/profile-aws/controls/iam_password_policy_expiration.rb +8 -8
  201. data/examples/profile-aws/controls/iam_password_policy_max_age.rb +8 -8
  202. data/examples/profile-aws/controls/iam_root_user_mfa.rb +8 -8
  203. data/examples/profile-aws/controls/iam_users_access_key_age.rb +8 -8
  204. data/examples/profile-aws/controls/iam_users_console_users_mfa.rb +8 -8
  205. data/examples/profile-aws/inspec.yml +11 -11
  206. data/examples/profile-azure/controls/azure_resource_group_example.rb +24 -24
  207. data/examples/profile-azure/controls/azure_vm_example.rb +29 -29
  208. data/examples/profile-azure/inspec.yml +11 -11
  209. data/examples/profile-sensitive/README.md +29 -29
  210. data/examples/profile-sensitive/controls/sensitive-failures.rb +9 -9
  211. data/examples/profile-sensitive/controls/sensitive.rb +9 -9
  212. data/examples/profile-sensitive/inspec.yml +8 -8
  213. data/examples/profile/README.md +48 -48
  214. data/examples/profile/controls/example.rb +23 -23
  215. data/examples/profile/controls/gordon.rb +36 -36
  216. data/examples/profile/controls/meta.rb +34 -34
  217. data/examples/profile/inspec.yml +10 -10
  218. data/examples/profile/libraries/gordon_config.rb +53 -53
  219. data/inspec.gemspec +47 -47
  220. data/lib/bundles/README.md +3 -3
  221. data/lib/bundles/inspec-artifact.rb +7 -7
  222. data/lib/bundles/inspec-artifact/README.md +1 -1
  223. data/lib/bundles/inspec-artifact/cli.rb +277 -277
  224. data/lib/bundles/inspec-compliance.rb +16 -16
  225. data/lib/bundles/inspec-compliance/.kitchen.yml +20 -20
  226. data/lib/bundles/inspec-compliance/README.md +185 -185
  227. data/lib/bundles/inspec-compliance/api.rb +316 -316
  228. data/lib/bundles/inspec-compliance/api/login.rb +152 -152
  229. data/lib/bundles/inspec-compliance/bootstrap.sh +41 -41
  230. data/lib/bundles/inspec-compliance/cli.rb +254 -254
  231. data/lib/bundles/inspec-compliance/configuration.rb +103 -103
  232. data/lib/bundles/inspec-compliance/http.rb +86 -86
  233. data/lib/bundles/inspec-compliance/support.rb +36 -36
  234. data/lib/bundles/inspec-compliance/target.rb +98 -98
  235. data/lib/bundles/inspec-compliance/test/integration/default/cli.rb +93 -93
  236. data/lib/bundles/inspec-habitat.rb +12 -12
  237. data/lib/bundles/inspec-habitat/cli.rb +36 -36
  238. data/lib/bundles/inspec-habitat/log.rb +10 -10
  239. data/lib/bundles/inspec-habitat/profile.rb +390 -390
  240. data/lib/bundles/inspec-init.rb +8 -8
  241. data/lib/bundles/inspec-init/README.md +31 -31
  242. data/lib/bundles/inspec-init/cli.rb +97 -97
  243. data/lib/bundles/inspec-init/templates/profile/README.md +3 -3
  244. data/lib/bundles/inspec-init/templates/profile/controls/example.rb +19 -19
  245. data/lib/bundles/inspec-init/templates/profile/inspec.yml +8 -8
  246. data/lib/bundles/inspec-supermarket.rb +13 -13
  247. data/lib/bundles/inspec-supermarket/README.md +45 -45
  248. data/lib/bundles/inspec-supermarket/api.rb +84 -84
  249. data/lib/bundles/inspec-supermarket/cli.rb +73 -73
  250. data/lib/bundles/inspec-supermarket/target.rb +34 -34
  251. data/lib/fetchers/git.rb +163 -163
  252. data/lib/fetchers/local.rb +74 -74
  253. data/lib/fetchers/mock.rb +35 -35
  254. data/lib/fetchers/url.rb +204 -204
  255. data/lib/inspec.rb +24 -24
  256. data/lib/inspec/archive/tar.rb +29 -29
  257. data/lib/inspec/archive/zip.rb +19 -19
  258. data/lib/inspec/backend.rb +93 -93
  259. data/lib/inspec/base_cli.rb +357 -355
  260. data/lib/inspec/cached_fetcher.rb +66 -66
  261. data/lib/inspec/cli.rb +292 -292
  262. data/lib/inspec/completions/bash.sh.erb +45 -45
  263. data/lib/inspec/completions/fish.sh.erb +34 -34
  264. data/lib/inspec/completions/zsh.sh.erb +61 -61
  265. data/lib/inspec/control_eval_context.rb +179 -179
  266. data/lib/inspec/dependencies/cache.rb +72 -72
  267. data/lib/inspec/dependencies/dependency_set.rb +92 -92
  268. data/lib/inspec/dependencies/lockfile.rb +115 -115
  269. data/lib/inspec/dependencies/requirement.rb +123 -123
  270. data/lib/inspec/dependencies/resolver.rb +86 -86
  271. data/lib/inspec/describe.rb +27 -27
  272. data/lib/inspec/dsl.rb +66 -66
  273. data/lib/inspec/dsl_shared.rb +33 -33
  274. data/lib/inspec/env_printer.rb +157 -157
  275. data/lib/inspec/errors.rb +13 -13
  276. data/lib/inspec/exceptions.rb +12 -12
  277. data/lib/inspec/expect.rb +45 -45
  278. data/lib/inspec/fetcher.rb +45 -45
  279. data/lib/inspec/file_provider.rb +275 -275
  280. data/lib/inspec/formatters.rb +3 -3
  281. data/lib/inspec/formatters/base.rb +250 -250
  282. data/lib/inspec/formatters/json_rspec.rb +20 -20
  283. data/lib/inspec/formatters/show_progress.rb +12 -12
  284. data/lib/inspec/library_eval_context.rb +58 -58
  285. data/lib/inspec/log.rb +11 -11
  286. data/lib/inspec/metadata.rb +247 -247
  287. data/lib/inspec/method_source.rb +24 -24
  288. data/lib/inspec/objects.rb +14 -14
  289. data/lib/inspec/objects/attribute.rb +65 -65
  290. data/lib/inspec/objects/control.rb +61 -61
  291. data/lib/inspec/objects/describe.rb +92 -92
  292. data/lib/inspec/objects/each_loop.rb +36 -36
  293. data/lib/inspec/objects/list.rb +15 -15
  294. data/lib/inspec/objects/or_test.rb +40 -40
  295. data/lib/inspec/objects/ruby_helper.rb +15 -15
  296. data/lib/inspec/objects/tag.rb +27 -27
  297. data/lib/inspec/objects/test.rb +87 -87
  298. data/lib/inspec/objects/value.rb +27 -27
  299. data/lib/inspec/plugins.rb +60 -60
  300. data/lib/inspec/plugins/cli.rb +24 -24
  301. data/lib/inspec/plugins/fetcher.rb +86 -86
  302. data/lib/inspec/plugins/resource.rb +135 -135
  303. data/lib/inspec/plugins/secret.rb +15 -15
  304. data/lib/inspec/plugins/source_reader.rb +40 -40
  305. data/lib/inspec/polyfill.rb +12 -12
  306. data/lib/inspec/profile.rb +510 -510
  307. data/lib/inspec/profile_context.rb +207 -207
  308. data/lib/inspec/profile_vendor.rb +66 -66
  309. data/lib/inspec/reporters.rb +54 -54
  310. data/lib/inspec/reporters/base.rb +24 -24
  311. data/lib/inspec/reporters/cli.rb +356 -356
  312. data/lib/inspec/reporters/json.rb +116 -116
  313. data/lib/inspec/reporters/json_min.rb +48 -48
  314. data/lib/inspec/reporters/junit.rb +77 -77
  315. data/lib/inspec/require_loader.rb +33 -33
  316. data/lib/inspec/resource.rb +186 -186
  317. data/lib/inspec/rule.rb +266 -266
  318. data/lib/inspec/runner.rb +345 -345
  319. data/lib/inspec/runner_mock.rb +41 -41
  320. data/lib/inspec/runner_rspec.rb +175 -175
  321. data/lib/inspec/runtime_profile.rb +26 -26
  322. data/lib/inspec/schema.rb +213 -213
  323. data/lib/inspec/secrets.rb +19 -19
  324. data/lib/inspec/secrets/yaml.rb +30 -30
  325. data/lib/inspec/shell.rb +220 -220
  326. data/lib/inspec/shell_detector.rb +90 -90
  327. data/lib/inspec/source_reader.rb +29 -29
  328. data/lib/inspec/version.rb +8 -8
  329. data/lib/matchers/matchers.rb +339 -339
  330. data/lib/resource_support/aws.rb +44 -41
  331. data/lib/resource_support/aws/aws_backend_base.rb +12 -12
  332. data/lib/resource_support/aws/aws_backend_factory_mixin.rb +12 -12
  333. data/lib/resource_support/aws/aws_plural_resource_mixin.rb +21 -21
  334. data/lib/resource_support/aws/aws_resource_mixin.rb +66 -66
  335. data/lib/resource_support/aws/aws_singular_resource_mixin.rb +24 -24
  336. data/lib/resources/aide_conf.rb +151 -159
  337. data/lib/resources/apache.rb +48 -48
  338. data/lib/resources/apache_conf.rb +149 -156
  339. data/lib/resources/apt.rb +149 -149
  340. data/lib/resources/audit_policy.rb +63 -63
  341. data/lib/resources/auditd.rb +231 -231
  342. data/lib/resources/auditd_conf.rb +46 -55
  343. data/lib/resources/aws/aws_cloudtrail_trail.rb +77 -77
  344. data/lib/resources/aws/aws_cloudtrail_trails.rb +47 -47
  345. data/lib/resources/aws/aws_cloudwatch_alarm.rb +62 -62
  346. data/lib/resources/aws/aws_cloudwatch_log_metric_filter.rb +100 -100
  347. data/lib/resources/aws/aws_config_recorder.rb +98 -98
  348. data/lib/resources/aws/aws_ec2_instance.rb +157 -157
  349. data/lib/resources/aws/aws_iam_access_key.rb +106 -106
  350. data/lib/resources/aws/aws_iam_access_keys.rb +149 -149
  351. data/lib/resources/aws/aws_iam_group.rb +56 -56
  352. data/lib/resources/aws/aws_iam_groups.rb +52 -52
  353. data/lib/resources/aws/aws_iam_password_policy.rb +116 -116
  354. data/lib/resources/aws/aws_iam_policies.rb +53 -53
  355. data/lib/resources/aws/aws_iam_policy.rb +125 -125
  356. data/lib/resources/aws/aws_iam_role.rb +51 -51
  357. data/lib/resources/aws/aws_iam_root_user.rb +60 -60
  358. data/lib/resources/aws/aws_iam_user.rb +111 -111
  359. data/lib/resources/aws/aws_iam_users.rb +108 -108
  360. data/lib/resources/aws/aws_kms_keys.rb +53 -53
  361. data/lib/resources/aws/aws_route_table.rb +61 -61
  362. data/lib/resources/aws/aws_s3_bucket.rb +115 -115
  363. data/lib/resources/aws/aws_s3_bucket_object.rb +82 -0
  364. data/lib/resources/aws/aws_security_group.rb +93 -93
  365. data/lib/resources/aws/aws_security_groups.rb +68 -68
  366. data/lib/resources/aws/aws_sns_subscription.rb +78 -0
  367. data/lib/resources/aws/aws_sns_topic.rb +53 -53
  368. data/lib/resources/aws/aws_sns_topics.rb +56 -0
  369. data/lib/resources/aws/aws_subnet.rb +88 -88
  370. data/lib/resources/aws/aws_subnets.rb +53 -53
  371. data/lib/resources/aws/aws_vpc.rb +69 -69
  372. data/lib/resources/aws/aws_vpcs.rb +45 -45
  373. data/lib/resources/azure/azure_backend.rb +377 -377
  374. data/lib/resources/azure/azure_generic_resource.rb +59 -59
  375. data/lib/resources/azure/azure_resource_group.rb +152 -152
  376. data/lib/resources/azure/azure_virtual_machine.rb +264 -264
  377. data/lib/resources/azure/azure_virtual_machine_data_disk.rb +136 -136
  378. data/lib/resources/bash.rb +35 -35
  379. data/lib/resources/bond.rb +69 -68
  380. data/lib/resources/bridge.rb +122 -122
  381. data/lib/resources/command.rb +73 -73
  382. data/lib/resources/cpan.rb +58 -58
  383. data/lib/resources/cran.rb +64 -64
  384. data/lib/resources/crontab.rb +169 -169
  385. data/lib/resources/csv.rb +56 -60
  386. data/lib/resources/dh_params.rb +77 -82
  387. data/lib/resources/directory.rb +25 -25
  388. data/lib/resources/docker.rb +236 -236
  389. data/lib/resources/docker_container.rb +89 -89
  390. data/lib/resources/docker_image.rb +83 -83
  391. data/lib/resources/docker_object.rb +57 -57
  392. data/lib/resources/docker_service.rb +90 -90
  393. data/lib/resources/elasticsearch.rb +169 -169
  394. data/lib/resources/etc_fstab.rb +94 -101
  395. data/lib/resources/etc_group.rb +152 -152
  396. data/lib/resources/etc_hosts.rb +66 -82
  397. data/lib/resources/etc_hosts_allow_deny.rb +112 -122
  398. data/lib/resources/file.rb +298 -298
  399. data/lib/resources/filesystem.rb +31 -31
  400. data/lib/resources/firewalld.rb +143 -143
  401. data/lib/resources/gem.rb +70 -70
  402. data/lib/resources/groups.rb +215 -215
  403. data/lib/resources/grub_conf.rb +227 -237
  404. data/lib/resources/host.rb +306 -306
  405. data/lib/resources/http.rb +251 -251
  406. data/lib/resources/iis_app.rb +101 -101
  407. data/lib/resources/iis_site.rb +148 -148
  408. data/lib/resources/inetd_conf.rb +54 -62
  409. data/lib/resources/ini.rb +29 -29
  410. data/lib/resources/interface.rb +129 -129
  411. data/lib/resources/iptables.rb +80 -80
  412. data/lib/resources/json.rb +107 -117
  413. data/lib/resources/kernel_module.rb +107 -107
  414. data/lib/resources/kernel_parameter.rb +58 -58
  415. data/lib/resources/key_rsa.rb +61 -67
  416. data/lib/resources/limits_conf.rb +46 -55
  417. data/lib/resources/login_def.rb +57 -66
  418. data/lib/resources/mount.rb +88 -88
  419. data/lib/resources/mssql_session.rb +101 -101
  420. data/lib/resources/mysql.rb +81 -81
  421. data/lib/resources/mysql_conf.rb +127 -134
  422. data/lib/resources/mysql_session.rb +85 -85
  423. data/lib/resources/nginx.rb +96 -96
  424. data/lib/resources/nginx_conf.rb +226 -227
  425. data/lib/resources/npm.rb +48 -48
  426. data/lib/resources/ntp_conf.rb +51 -58
  427. data/lib/resources/oneget.rb +71 -71
  428. data/lib/resources/oracledb_session.rb +139 -139
  429. data/lib/resources/os.rb +36 -36
  430. data/lib/resources/os_env.rb +76 -76
  431. data/lib/resources/package.rb +370 -370
  432. data/lib/resources/packages.rb +111 -111
  433. data/lib/resources/parse_config.rb +112 -116
  434. data/lib/resources/passwd.rb +76 -74
  435. data/lib/resources/pip.rb +89 -89
  436. data/lib/resources/platform.rb +109 -109
  437. data/lib/resources/port.rb +771 -771
  438. data/lib/resources/postgres.rb +130 -130
  439. data/lib/resources/postgres_conf.rb +114 -121
  440. data/lib/resources/postgres_hba_conf.rb +90 -99
  441. data/lib/resources/postgres_ident_conf.rb +79 -76
  442. data/lib/resources/postgres_session.rb +71 -71
  443. data/lib/resources/powershell.rb +53 -53
  444. data/lib/resources/processes.rb +204 -204
  445. data/lib/resources/rabbitmq_conf.rb +51 -52
  446. data/lib/resources/registry_key.rb +296 -296
  447. data/lib/resources/security_policy.rb +180 -180
  448. data/lib/resources/service.rb +790 -789
  449. data/lib/resources/shadow.rb +149 -146
  450. data/lib/resources/ssh_conf.rb +97 -102
  451. data/lib/resources/ssl.rb +99 -99
  452. data/lib/resources/sys_info.rb +28 -28
  453. data/lib/resources/toml.rb +32 -32
  454. data/lib/resources/users.rb +654 -654
  455. data/lib/resources/vbscript.rb +68 -68
  456. data/lib/resources/virtualization.rb +247 -247
  457. data/lib/resources/windows_feature.rb +84 -84
  458. data/lib/resources/windows_hotfix.rb +35 -35
  459. data/lib/resources/windows_task.rb +102 -102
  460. data/lib/resources/wmi.rb +110 -110
  461. data/lib/resources/x509_certificate.rb +137 -143
  462. data/lib/resources/xinetd.rb +106 -111
  463. data/lib/resources/xml.rb +46 -46
  464. data/lib/resources/yaml.rb +43 -47
  465. data/lib/resources/yum.rb +180 -180
  466. data/lib/resources/zfs_dataset.rb +60 -60
  467. data/lib/resources/zfs_pool.rb +49 -49
  468. data/lib/source_readers/flat.rb +39 -39
  469. data/lib/source_readers/inspec.rb +75 -75
  470. data/lib/utils/command_wrapper.rb +27 -27
  471. data/lib/utils/convert.rb +12 -12
  472. data/lib/utils/database_helpers.rb +77 -77
  473. data/lib/utils/erlang_parser.rb +192 -192
  474. data/lib/utils/file_reader.rb +25 -0
  475. data/lib/utils/filter.rb +272 -272
  476. data/lib/utils/filter_array.rb +27 -27
  477. data/lib/utils/find_files.rb +44 -44
  478. data/lib/utils/hash.rb +41 -41
  479. data/lib/utils/json_log.rb +18 -18
  480. data/lib/utils/latest_version.rb +22 -22
  481. data/lib/utils/modulator.rb +12 -12
  482. data/lib/utils/nginx_parser.rb +85 -85
  483. data/lib/utils/object_traversal.rb +49 -49
  484. data/lib/utils/parser.rb +274 -274
  485. data/lib/utils/plugin_registry.rb +93 -93
  486. data/lib/utils/simpleconfig.rb +120 -120
  487. data/lib/utils/spdx.rb +13 -13
  488. data/lib/utils/spdx.txt +343 -343
  489. metadata +12 -5
@@ -1,180 +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
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
@@ -1,789 +1,790 @@
1
- # encoding: utf-8
2
-
3
- require 'hashie'
4
-
5
- module Inspec::Resources
6
- class Runlevels < Hash
7
- attr_accessor :owner
8
-
9
- def self.from_hash(owner, hash = {}, filter = nil)
10
- res = Runlevels.new(owner)
11
- filter = filter.first if filter.is_a?(Array) && filter.length <= 1
12
-
13
- ks = case filter
14
- when nil
15
- hash.keys
16
- when Regexp
17
- hash.keys.find_all { |x| x.to_s =~ filter }
18
- when Array
19
- f = filter.map(&:to_s)
20
- hash.keys.find_all { |x| f.include?(x.to_s) }
21
- when Numeric
22
- hash.keys.include?(filter) ? [filter] : []
23
- else
24
- hash.keys.find_all { |x| x == filter }
25
- end
26
-
27
- ks.each { |k| res[k] = hash[k] }
28
- res
29
- end
30
-
31
- def initialize(owner, default = false)
32
- @owner = owner
33
- super(default)
34
- end
35
-
36
- def filter(f)
37
- Runlevels.from_hash(owner, self, f)
38
- end
39
-
40
- # Check if all runlevels are enabled
41
- #
42
- # @return [boolean] true if all runlevels are enabled
43
- def enabled?
44
- values.all?
45
- end
46
-
47
- # Check if all runlevels are disabled
48
- #
49
- # @return [boolean] true if all runlevels are disabled
50
- def disabled?
51
- values.none?
52
- end
53
-
54
- def to_s
55
- "#{owner} runlevels #{keys.join(', ')}"
56
- end
57
- end
58
-
59
- # We detect the init system for each operating system, based on the operating
60
- # system.
61
- #
62
- # Fedora 15 : systemd
63
- # RedHat 7 : systemd
64
- # Ubuntu 15.04 : systemd
65
- # Ubuntu < 15.04 : upstart
66
- #
67
- # TODO: extend the logic to detect the running init system, independently of OS
68
- class Service < Inspec.resource(1)
69
- name 'service'
70
- supports platform: 'unix'
71
- supports platform: 'windows'
72
- desc 'Use the service InSpec audit resource to test if the named service is installed, running and/or enabled.'
73
- example "
74
- describe service('service_name') do
75
- it { should be_installed }
76
- it { should be_enabled }
77
- it { should be_running }
78
- its('type') { should be 'systemd' }
79
- its ('startmode') { should be 'Auto'}
80
- end
81
-
82
- describe service('service_name').runlevels(3, 5) do
83
- it { should be_enabled }
84
- end
85
-
86
- describe service('service_name').params do
87
- its('UnitFileState') { should eq 'enabled' }
88
- end
89
- "
90
-
91
- attr_reader :service_ctl
92
-
93
- def initialize(service_name, service_ctl = nil)
94
- @service_name = service_name
95
- @service_mgmt = nil
96
- @service_ctl ||= service_ctl
97
- @cache = nil
98
- @service_mgmt = select_service_mgmt
99
-
100
- return skip_resource 'The `service` resource is not supported on your OS yet.' if @service_mgmt.nil?
101
- end
102
-
103
- def select_service_mgmt # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
104
- os = inspec.os
105
- platform = os[:name]
106
-
107
- # Ubuntu
108
- # @see: https://wiki.ubuntu.com/SystemdForUpstartUsers
109
- # Ubuntu 15.04 : Systemd
110
- # Systemd runs with PID 1 as /sbin/init.
111
- # Upstart runs with PID 1 as /sbin/upstart.
112
- # Ubuntu < 15.04 : Upstart
113
- # Upstart runs with PID 1 as /sbin/init.
114
- # Systemd runs with PID 1 as /lib/systemd/systemd.
115
- if %w{ubuntu}.include?(platform)
116
- version = os[:release].to_f
117
- if version < 15.04
118
- Upstart.new(inspec, service_ctl)
119
- else
120
- Systemd.new(inspec, service_ctl)
121
- end
122
- elsif %w{linuxmint}.include?(platform)
123
- version = os[:release].to_f
124
- if version < 18
125
- Upstart.new(inspec, service_ctl)
126
- else
127
- Systemd.new(inspec, service_ctl)
128
- end
129
- elsif %w{debian}.include?(platform)
130
- version = os[:release].to_i
131
- if version > 7
132
- Systemd.new(inspec, service_ctl)
133
- else
134
- SysV.new(inspec, service_ctl || '/usr/sbin/service')
135
- end
136
- elsif %w{redhat fedora centos oracle}.include?(platform)
137
- version = os[:release].to_i
138
- if (%w{redhat centos oracle}.include?(platform) && version >= 7) || (platform == 'fedora' && version >= 15)
139
- Systemd.new(inspec, service_ctl)
140
- else
141
- SysV.new(inspec, service_ctl || '/sbin/service')
142
- end
143
- elsif %w{wrlinux}.include?(platform)
144
- SysV.new(inspec, service_ctl)
145
- elsif %w{mac_os_x}.include?(platform)
146
- LaunchCtl.new(inspec, service_ctl)
147
- elsif os.windows?
148
- WindowsSrv.new(inspec)
149
- elsif %w{freebsd}.include?(platform)
150
- BSDInit.new(inspec, service_ctl)
151
- elsif %w{arch}.include?(platform)
152
- Systemd.new(inspec, service_ctl)
153
- elsif %w{coreos}.include?(platform)
154
- Systemd.new(inspec, service_ctl)
155
- elsif %w{suse opensuse}.include?(platform)
156
- if os[:release].to_i >= 12
157
- Systemd.new(inspec, service_ctl)
158
- else
159
- SysV.new(inspec, service_ctl || '/sbin/service')
160
- end
161
- elsif %w{aix}.include?(platform)
162
- SrcMstr.new(inspec)
163
- elsif %w{amazon}.include?(platform)
164
- Upstart.new(inspec, service_ctl)
165
- elsif os.solaris?
166
- Svcs.new(inspec)
167
- end
168
- end
169
-
170
- def info
171
- return nil if @service_mgmt.nil?
172
- @cache ||= @service_mgmt.info(@service_name)
173
- end
174
-
175
- # verifies if the service is enabled
176
- def enabled?(_level = nil)
177
- return false if info.nil?
178
- info[:enabled]
179
- end
180
-
181
- def params
182
- return {} if info.nil?
183
- Hashie::Mash.new(info[:params] || {})
184
- end
185
-
186
- # verifies the service is registered
187
- def installed?(_name = nil, _version = nil)
188
- return false if info.nil?
189
- info[:installed]
190
- end
191
-
192
- # verifies the service is currently running
193
- def running?(_under = nil)
194
- return false if info.nil?
195
- info[:running]
196
- end
197
-
198
- # get all runlevels that are available and their configuration
199
- def runlevels(*args)
200
- return Runlevels.new(self) if info.nil? or info[:runlevels].nil?
201
- Runlevels.from_hash(self, info[:runlevels], args)
202
- end
203
-
204
- # returns the service type from info
205
- def type
206
- return nil if info.nil?
207
- info[:type]
208
- end
209
-
210
- # returns the service name from info
211
- def name
212
- return @service_name if info.nil?
213
- info[:name]
214
- end
215
-
216
- # returns the service description from info
217
- def description
218
- return nil if info.nil?
219
- info[:description]
220
- end
221
-
222
- # returns the service start up mode from info
223
- def startmode
224
- return nil if info.nil?
225
- info[:startmode]
226
- end
227
-
228
- def to_s
229
- "Service #{@service_name}"
230
- end
231
-
232
- private :info
233
- end
234
-
235
- class ServiceManager
236
- attr_reader :inspec, :service_ctl
237
- def initialize(inspec, service_ctl = nil)
238
- @inspec = inspec
239
- @service_ctl ||= service_ctl
240
- end
241
- end
242
-
243
- # @see: http://www.freedesktop.org/software/systemd/man/systemctl.html
244
- # @see: http://www.freedesktop.org/software/systemd/man/systemd-system.conf.html
245
- class Systemd < ServiceManager
246
- def initialize(inspec, service_ctl = nil)
247
- @service_ctl = service_ctl || 'systemctl'
248
- super
249
- end
250
-
251
- def is_enabled?(service_name)
252
- result = inspec.command("#{service_ctl} is-enabled #{service_name} --quiet")
253
- return true if result.exit_status == 0
254
-
255
- # Some systems may not have a `.service` file for a particular service
256
- # which causes the `systemctl is-enabled` check to fail despite the
257
- # service being enabled. In that event we fallback to `sysv_service`.
258
- if result.stderr =~ /Failed to get.*No such file or directory/
259
- return inspec.sysv_service(service_name).enabled?
260
- end
261
-
262
- false
263
- end
264
-
265
- def is_active?(service_name)
266
- inspec.command("#{service_ctl} is-active #{service_name} --quiet").exit_status == 0
267
- end
268
-
269
- def info(service_name)
270
- cmd = inspec.command("#{service_ctl} show --all #{service_name}")
271
- return nil if cmd.exit_status.to_i != 0
272
-
273
- # parse data
274
- params = SimpleConfig.new(
275
- cmd.stdout.chomp,
276
- assignment_regex: /^\s*([^=]*?)\s*=\s*(.*?)\s*$/,
277
- multiple_values: false,
278
- ).params
279
-
280
- # LoadState values eg. loaded, not-found
281
- installed = params['LoadState'] == 'loaded'
282
-
283
- {
284
- name: params['Id'],
285
- description: params['Description'],
286
- installed: installed,
287
- running: is_active?(service_name),
288
- enabled: is_enabled?(service_name),
289
- type: 'systemd',
290
- params: params,
291
- }
292
- end
293
- end
294
-
295
- # AIX services
296
- class SrcMstr < ServiceManager
297
- attr_reader :name
298
-
299
- def info(service_name)
300
- @name = service_name
301
- running = status?
302
- return nil if running.nil?
303
-
304
- {
305
- name: service_name,
306
- description: nil,
307
- installed: true,
308
- running: running,
309
- enabled: enabled?,
310
- type: 'srcmstr',
311
- }
312
- end
313
-
314
- private
315
-
316
- def status?
317
- status_cmd = inspec.command("lssrc -s #{@name}")
318
- return nil if status_cmd.exit_status.to_i != 0
319
- status_cmd.stdout.split(/\n/).last.chomp =~ /active$/ ? true : false
320
- end
321
-
322
- def enabled?
323
- enabled_rc_tcpip? || enabled_inittab?
324
- end
325
-
326
- def enabled_rc_tcpip?
327
- inspec.command(
328
- "grep -v ^# /etc/rc.tcpip | grep 'start ' | grep -Eq '(/{0,1}| )#{name} '",
329
- ).exit_status == 0
330
- end
331
-
332
- def enabled_inittab?
333
- inspec.command("lsitab #{name}").exit_status == 0
334
- end
335
- end
336
-
337
- # @see: http://upstart.ubuntu.com
338
- class Upstart < ServiceManager
339
- def initialize(service_name, service_ctl = nil)
340
- @service_ctl = service_ctl || 'initctl'
341
- super
342
- end
343
-
344
- def info(service_name)
345
- # get the status of upstart service
346
- status = inspec.command("#{service_ctl} status #{service_name}")
347
-
348
- # fallback for systemv services, those are not handled via `initctl`
349
- return SysV.new(inspec).info(service_name) if status.exit_status.to_i != 0 || status.stdout == ''
350
-
351
- # @see: http://upstart.ubuntu.com/cookbook/#job-states
352
- # grep for running to indicate the service is there
353
- running = !status.stdout[%r{start/running}].nil?
354
-
355
- {
356
- name: service_name,
357
- description: nil,
358
- installed: true,
359
- running: running,
360
- enabled: info_enabled(service_name),
361
- type: 'upstart',
362
- }
363
- end
364
-
365
- private
366
-
367
- def info_enabled(service_name)
368
- # check if a service is enabled
369
- config = inspec.file("/etc/init/#{service_name}.conf").content
370
-
371
- # disregard if the config does not exist
372
- return nil if config.nil?
373
-
374
- !config.match(/^\s*start on/).nil?
375
- end
376
-
377
- def version
378
- @version ||= begin
379
- out = inspec.command("#{service_ctl} --version").stdout
380
- Gem::Version.new(out[/\(upstart ([^\)]+)\)/, 1])
381
- end
382
- end
383
- end
384
-
385
- class SysV < ServiceManager
386
- RUNLEVELS = { 0=>false, 1=>false, 2=>false, 3=>false, 4=>false, 5=>false, 6=>false }.freeze
387
-
388
- def initialize(service_name, service_ctl = nil)
389
- @service_ctl = service_ctl || 'service'
390
- super
391
- end
392
-
393
- def info(service_name)
394
- # check if service is installed
395
- # read all available services via ls /etc/init.d/
396
- srvlist = inspec.command('ls -1 /etc/init.d/')
397
- return nil if srvlist.exit_status != 0
398
-
399
- # check if the service is in list
400
- service = srvlist.stdout.split("\n").select { |srv| srv == service_name }
401
-
402
- # abort if we could not find any service
403
- return nil if service.empty?
404
-
405
- # read all enabled services from runlevel
406
- # on rhel via: 'chkconfig --list', is not installed by default
407
- # bash: for i in `find /etc/rc*.d -name S*`; do basename $i | sed -r 's/^S[0-9]+//'; done | sort | uniq
408
- enabled_services_cmd = inspec.command('find /etc/rc*.d /etc/init.d/rc*.d -name "S*"').stdout
409
- service_line = %r{rc(?<runlevel>[0-6])\.d/S[^/]*?#{Regexp.escape service_name}$}
410
- all_services = enabled_services_cmd.split("\n").map { |line|
411
- service_line.match(line)
412
- }.compact
413
- enabled = !all_services.empty?
414
-
415
- # Determine a list of runlevels which this service is activated for
416
- runlevels = RUNLEVELS.dup
417
- all_services.each { |x| runlevels[x[:runlevel].to_i] = true }
418
-
419
- # check if service is really running
420
- # service throws an exit code if the service is not installed or
421
- # not enabled
422
-
423
- cmd = inspec.command("#{service_ctl} #{service_name} status")
424
- running = cmd.exit_status == 0
425
- {
426
- name: service_name,
427
- description: nil,
428
- installed: true,
429
- running: running,
430
- enabled: enabled,
431
- runlevels: runlevels,
432
- type: 'sysv',
433
- }
434
- end
435
- end
436
-
437
- # @see: https://www.freebsd.org/doc/en/articles/linux-users/startup.html
438
- # @see: https://www.freebsd.org/cgi/man.cgi?query=rc.conf&sektion=5
439
- class BSDInit < ServiceManager
440
- def initialize(service_name, service_ctl = nil)
441
- @service_ctl = service_ctl || 'service'
442
- super
443
- end
444
-
445
- def info(service_name)
446
- # check if service is enabled
447
- # services are enabled in /etc/rc.conf and /etc/defaults/rc.conf
448
- # via #{service_name}_enable="YES"
449
- # service SERVICE status returns the following result if not activated:
450
- # Cannot 'status' sshd. Set sshd_enable to YES in /etc/rc.conf or use 'onestatus' instead of 'status'.
451
- # gather all enabled services
452
- cmd = inspec.command("#{service_ctl} -e")
453
- return nil if cmd.exit_status != 0
454
-
455
- # search for the service
456
- srv = /(^.*#{service_name}$)/.match(cmd.stdout)
457
- return nil if srv.nil? || srv[0].nil?
458
- enabled = true
459
-
460
- # check if the service is running
461
- # if the service is not available or not running, we always get an error code
462
- cmd = inspec.command("#{service_ctl} #{service_name} onestatus")
463
- running = cmd.exit_status == 0
464
-
465
- {
466
- name: service_name,
467
- description: nil,
468
- installed: true,
469
- running: running,
470
- enabled: enabled,
471
- type: 'bsd-init',
472
- }
473
- end
474
- end
475
-
476
- class Runit < ServiceManager
477
- def initialize(service_name, service_ctl = nil)
478
- @service_ctl = service_ctl || 'sv'
479
- super
480
- end
481
-
482
- # rubocop:disable Style/DoubleNegation
483
- def info(service_name)
484
- # get the status of runit service
485
- cmd = inspec.command("#{service_ctl} status #{service_name}")
486
- # return nil unless cmd.exit_status == 0 # NOTE(sr) why do we do this?
487
-
488
- installed = cmd.exit_status == 0
489
- running = installed && !!(cmd.stdout =~ /^run:/)
490
- enabled = installed && (running || !!(cmd.stdout =~ /normally up/) || !!(cmd.stdout =~ /want up/))
491
-
492
- {
493
- name: service_name,
494
- description: nil,
495
- installed: installed,
496
- running: running,
497
- enabled: enabled,
498
- type: 'runit',
499
- }
500
- end
501
- end
502
-
503
- # MacOS / Darwin
504
- # new launctl on macos 10.10
505
- class LaunchCtl < ServiceManager
506
- def initialize(service_name, service_ctl = nil)
507
- @service_ctl = service_ctl || 'launchctl'
508
- super
509
- end
510
-
511
- def info(service_name)
512
- # get the status of upstart service
513
- cmd = inspec.command("#{service_ctl} list")
514
- return nil if cmd.exit_status != 0
515
-
516
- # search for the service
517
- srv = /(^.*#{service_name}.*)/.match(cmd.stdout)
518
- return nil if srv.nil? || srv[0].nil?
519
-
520
- # extract values from service
521
- parsed_srv = /^(?<pid>[0-9-]+)\t(?<exit>[0-9]+)\t(?<name>\S*)$/.match(srv[0])
522
- enabled = !parsed_srv['name'].nil? # it's in the list
523
-
524
- # check if the service is running
525
- pid = parsed_srv['pid']
526
- running = pid != '-'
527
-
528
- # extract service label
529
- srv = parsed_srv['name'] || service_name
530
-
531
- {
532
- name: srv,
533
- description: nil,
534
- installed: true,
535
- running: running,
536
- enabled: enabled,
537
- type: 'darwin',
538
- }
539
- end
540
- end
541
-
542
- # Determine the service state from Windows
543
- # Uses Powershell to retrieve the information
544
- class WindowsSrv < ServiceManager
545
- # Determine service details
546
- # PS: Get-Service -Name 'dhcp'| Select-Object -Property Name, DisplayName, Status | ConvertTo-Json
547
- # {
548
- # "Name": "dhcp",
549
- # "DisplayName": "DHCP Client",
550
- # "Status": 4
551
- # }
552
- #
553
- # Until StartMode is not added to Get-Service, we need to do a workaround
554
- # @see: https://connect.microsoft.com/PowerShell/feedback/details/424948/i-would-like-to-see-the-property-starttype-added-to-get-services
555
- # Also see: https://msdn.microsoft.com/en-us/library/aa384896(v=vs.85).aspx
556
- # Use the following powershell to determine the start mode
557
- # PS: Get-WmiObject -Class Win32_Service | Where-Object {$_.Name -eq $name -or $_.DisplayName -eq $name} | Select-Object -Prop
558
- # erty Name, StartMode, State, Status | ConvertTo-Json
559
- # {
560
- # "Name": "Dhcp",
561
- # "StartMode": "Auto",
562
- # "State": "Running",
563
- # "Status": "OK"
564
- # }
565
- #
566
- # Windows Services have the following status code:
567
- # @see: https://msdn.microsoft.com/en-us/library/windows/desktop/ms685996(v=vs.85).aspx
568
- # - 1: Stopped
569
- # - 2: Starting
570
- # - 3: Stopping
571
- # - 4: Running
572
- # - 5: Continue Pending
573
- # - 6: Pause Pending
574
- # - 7: Paused
575
- def info(service_name)
576
- 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")
577
-
578
- # cannot rely on exit code for now, successful command returns exit code 1
579
- # return nil if cmd.exit_status != 0
580
- # try to parse json
581
- begin
582
- service = JSON.parse(cmd.stdout)
583
- rescue JSON::ParserError => _e
584
- return nil
585
- end
586
-
587
- # check that we got a response
588
- return nil if service.nil? || service['Service'].nil?
589
-
590
- {
591
- name: service['Service']['Name'],
592
- description: service['Service']['DisplayName'],
593
- installed: true,
594
- running: service_running?(service),
595
- enabled: service_enabled?(service),
596
- startmode: service['WMI']['StartMode'],
597
- type: 'windows',
598
- }
599
- end
600
-
601
- private
602
-
603
- # detect if service is enabled
604
- def service_enabled?(service)
605
- !service['WMI'].nil? &&
606
- !service['WMI']['StartMode'].nil? &&
607
- (service['WMI']['StartMode'] == 'Auto' ||
608
- service['WMI']['StartMode'] == 'Manual')
609
- end
610
-
611
- # detect if service is running
612
- def service_running?(service)
613
- !service['Service']['Status'].nil? && service['Service']['Status'] == 4
614
- end
615
- end
616
-
617
- # Solaris services
618
- class Svcs < ServiceManager
619
- def initialize(service_name, service_ctl = nil)
620
- @service_ctl = service_ctl || 'svcs'
621
- super
622
- end
623
-
624
- def info(service_name)
625
- # get the status of runit service
626
- cmd = inspec.command("#{service_ctl} -l #{service_name}")
627
- return nil if cmd.exit_status != 0
628
-
629
- params = SimpleConfig.new(
630
- cmd.stdout.chomp,
631
- assignment_regex: /^(\w+)\s*(.*)$/,
632
- multiple_values: false,
633
- ).params
634
-
635
- installed = cmd.exit_status == 0
636
- running = installed && (params['state'] == 'online')
637
- enabled = installed && (params['enabled'] == 'true')
638
-
639
- {
640
- name: service_name,
641
- description: params['name'],
642
- installed: installed,
643
- running: running,
644
- enabled: enabled,
645
- type: 'svcs',
646
- }
647
- end
648
- end
649
-
650
- # specific resources for specific service managers
651
-
652
- class SystemdService < Service
653
- name 'systemd_service'
654
- supports platform: 'unix'
655
- desc 'Use the systemd_service InSpec audit resource to test if the named service (controlled by systemd) is installed, running and/or enabled.'
656
- example "
657
- # to override service mgmt auto-detection
658
- describe systemd_service('service_name') do
659
- it { should be_installed }
660
- it { should be_enabled }
661
- it { should be_running }
662
- end
663
-
664
- # to set a non-standard systemctl path
665
- describe systemd_service('service_name', '/path/to/systemctl') do
666
- it { should be_running }
667
- end
668
- "
669
-
670
- def select_service_mgmt
671
- Systemd.new(inspec, service_ctl)
672
- end
673
- end
674
-
675
- class UpstartService < Service
676
- name 'upstart_service'
677
- supports platform: 'unix'
678
- desc 'Use the upstart_service InSpec audit resource to test if the named service (controlled by upstart) is installed, running and/or enabled.'
679
- example "
680
- # to override service mgmt auto-detection
681
- describe upstart_service('service_name') do
682
- it { should be_installed }
683
- it { should be_enabled }
684
- it { should be_running }
685
- end
686
-
687
- # to set a non-standard initctl path
688
- describe upstart_service('service_name', '/path/to/initctl') do
689
- it { should be_running }
690
- end
691
- "
692
-
693
- def select_service_mgmt
694
- Upstart.new(inspec, service_ctl)
695
- end
696
- end
697
-
698
- class SysVService < Service
699
- name 'sysv_service'
700
- supports platform: 'unix'
701
- desc 'Use the sysv_service InSpec audit resource to test if the named service (controlled by SysV) is installed, running and/or enabled.'
702
- example "
703
- # to override service mgmt auto-detection
704
- describe sysv_service('service_name') do
705
- it { should be_installed }
706
- it { should be_enabled }
707
- it { should be_running }
708
- end
709
-
710
- # to set a non-standard service path
711
- describe sysv_service('service_name', '/path/to/service') do
712
- it { should be_running }
713
- end
714
- "
715
-
716
- def select_service_mgmt
717
- SysV.new(inspec, service_ctl)
718
- end
719
- end
720
-
721
- class BSDService < Service
722
- name 'bsd_service'
723
- supports platform: 'unix'
724
- desc 'Use the bsd_service InSpec audit resource to test if the named service (controlled by BSD init) is installed, running and/or enabled.'
725
- example "
726
- # to override service mgmt auto-detection
727
- describe bsd_service('service_name') do
728
- it { should be_installed }
729
- it { should be_enabled }
730
- it { should be_running }
731
- end
732
-
733
- # to set a non-standard service path
734
- describe bsd_service('service_name', '/path/to/service') do
735
- it { should be_running }
736
- end
737
- "
738
-
739
- def select_service_mgmt
740
- BSDInit.new(inspec, service_ctl)
741
- end
742
- end
743
-
744
- class LaunchdService < Service
745
- name 'launchd_service'
746
- supports platform: 'unix'
747
- desc 'Use the launchd_service InSpec audit resource to test if the named service (controlled by launchd) is installed, running and/or enabled.'
748
- example "
749
- # to override service mgmt auto-detection
750
- describe launchd_service('service_name') do
751
- it { should be_installed }
752
- it { should be_enabled }
753
- it { should be_running }
754
- end
755
-
756
- # to set a non-standard launchctl path
757
- describe launchd_service('service_name', '/path/to/launchctl') do
758
- it { should be_running }
759
- end
760
- "
761
-
762
- def select_service_mgmt
763
- LaunchCtl.new(inspec, service_ctl)
764
- end
765
- end
766
-
767
- class RunitService < Service
768
- name 'runit_service'
769
- supports platform: 'unix'
770
- desc 'Use the runit_service InSpec audit resource to test if the named service (controlled by runit) is installed, running and/or enabled.'
771
- example "
772
- # to override service mgmt auto-detection
773
- describe runit_service('service_name') do
774
- it { should be_installed }
775
- it { should be_enabled }
776
- it { should be_running }
777
- end
778
-
779
- # to set a non-standard sv path
780
- describe runit_service('service_name', '/path/to/sv') do
781
- it { should be_running }
782
- end
783
- "
784
-
785
- def select_service_mgmt
786
- Runit.new(inspec, service_ctl)
787
- end
788
- end
789
- end
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
+ Upstart.new(inspec, service_ctl)
166
+ elsif os.solaris?
167
+ Svcs.new(inspec)
168
+ end
169
+ end
170
+
171
+ def info
172
+ return nil if @service_mgmt.nil?
173
+ @cache ||= @service_mgmt.info(@service_name)
174
+ end
175
+
176
+ # verifies if the service is enabled
177
+ def enabled?(_level = nil)
178
+ return false if info.nil?
179
+ info[:enabled]
180
+ end
181
+
182
+ def params
183
+ return {} if info.nil?
184
+ Hashie::Mash.new(info[:params] || {})
185
+ end
186
+
187
+ # verifies the service is registered
188
+ def installed?(_name = nil, _version = nil)
189
+ return false if info.nil?
190
+ info[:installed]
191
+ end
192
+
193
+ # verifies the service is currently running
194
+ def running?(_under = nil)
195
+ return false if info.nil?
196
+ info[:running]
197
+ end
198
+
199
+ # get all runlevels that are available and their configuration
200
+ def runlevels(*args)
201
+ return Runlevels.new(self) if info.nil? or info[:runlevels].nil?
202
+ Runlevels.from_hash(self, info[:runlevels], args)
203
+ end
204
+
205
+ # returns the service type from info
206
+ def type
207
+ return nil if info.nil?
208
+ info[:type]
209
+ end
210
+
211
+ # returns the service name from info
212
+ def name
213
+ return @service_name if info.nil?
214
+ info[:name]
215
+ end
216
+
217
+ # returns the service description from info
218
+ def description
219
+ return nil if info.nil?
220
+ info[:description]
221
+ end
222
+
223
+ # returns the service start up mode from info
224
+ def startmode
225
+ return nil if info.nil?
226
+ info[:startmode]
227
+ end
228
+
229
+ def to_s
230
+ "Service #{@service_name}"
231
+ end
232
+
233
+ private :info
234
+ end
235
+
236
+ class ServiceManager
237
+ attr_reader :inspec, :service_ctl
238
+ def initialize(inspec, service_ctl = nil)
239
+ @inspec = inspec
240
+ @service_ctl ||= service_ctl
241
+ end
242
+ end
243
+
244
+ # @see: http://www.freedesktop.org/software/systemd/man/systemctl.html
245
+ # @see: http://www.freedesktop.org/software/systemd/man/systemd-system.conf.html
246
+ class Systemd < ServiceManager
247
+ def initialize(inspec, service_ctl = nil)
248
+ @service_ctl = service_ctl || 'systemctl'
249
+ super
250
+ end
251
+
252
+ def is_enabled?(service_name)
253
+ result = inspec.command("#{service_ctl} is-enabled #{service_name} --quiet")
254
+ return true if result.exit_status == 0
255
+
256
+ # Some systems may not have a `.service` file for a particular service
257
+ # which causes the `systemctl is-enabled` check to fail despite the
258
+ # service being enabled. In that event we fallback to `sysv_service`.
259
+ if result.stderr =~ /Failed to get.*No such file or directory/
260
+ return inspec.sysv_service(service_name).enabled?
261
+ end
262
+
263
+ false
264
+ end
265
+
266
+ def is_active?(service_name)
267
+ inspec.command("#{service_ctl} is-active #{service_name} --quiet").exit_status == 0
268
+ end
269
+
270
+ def info(service_name)
271
+ cmd = inspec.command("#{service_ctl} show --all #{service_name}")
272
+ return nil if cmd.exit_status.to_i != 0
273
+
274
+ # parse data
275
+ params = SimpleConfig.new(
276
+ cmd.stdout.chomp,
277
+ assignment_regex: /^\s*([^=]*?)\s*=\s*(.*?)\s*$/,
278
+ multiple_values: false,
279
+ ).params
280
+
281
+ # LoadState values eg. loaded, not-found
282
+ installed = params['LoadState'] == 'loaded'
283
+
284
+ {
285
+ name: params['Id'],
286
+ description: params['Description'],
287
+ installed: installed,
288
+ running: is_active?(service_name),
289
+ enabled: is_enabled?(service_name),
290
+ type: 'systemd',
291
+ params: params,
292
+ }
293
+ end
294
+ end
295
+
296
+ # AIX services
297
+ class SrcMstr < ServiceManager
298
+ attr_reader :name
299
+
300
+ def info(service_name)
301
+ @name = service_name
302
+ running = status?
303
+ return nil if running.nil?
304
+
305
+ {
306
+ name: service_name,
307
+ description: nil,
308
+ installed: true,
309
+ running: running,
310
+ enabled: enabled?,
311
+ type: 'srcmstr',
312
+ }
313
+ end
314
+
315
+ private
316
+
317
+ def status?
318
+ status_cmd = inspec.command("lssrc -s #{@name}")
319
+ return nil if status_cmd.exit_status.to_i != 0
320
+ status_cmd.stdout.split(/\n/).last.chomp =~ /active$/ ? true : false
321
+ end
322
+
323
+ def enabled?
324
+ enabled_rc_tcpip? || enabled_inittab?
325
+ end
326
+
327
+ def enabled_rc_tcpip?
328
+ inspec.command(
329
+ "grep -v ^# /etc/rc.tcpip | grep 'start ' | grep -Eq '(/{0,1}| )#{name} '",
330
+ ).exit_status == 0
331
+ end
332
+
333
+ def enabled_inittab?
334
+ inspec.command("lsitab #{name}").exit_status == 0
335
+ end
336
+ end
337
+
338
+ # @see: http://upstart.ubuntu.com
339
+ class Upstart < ServiceManager
340
+ include FileReader
341
+
342
+ def initialize(service_name, service_ctl = nil)
343
+ @service_ctl = service_ctl || 'initctl'
344
+ super
345
+ end
346
+
347
+ def info(service_name)
348
+ # get the status of upstart service
349
+ status = inspec.command("#{service_ctl} status #{service_name}")
350
+
351
+ # fallback for systemv services, those are not handled via `initctl`
352
+ return SysV.new(inspec).info(service_name) if status.exit_status.to_i != 0 || status.stdout == ''
353
+
354
+ # @see: http://upstart.ubuntu.com/cookbook/#job-states
355
+ # grep for running to indicate the service is there
356
+ running = !status.stdout[%r{start/running}].nil?
357
+ enabled = info_enabled(service_name)
358
+
359
+ {
360
+ name: service_name,
361
+ description: nil,
362
+ installed: true,
363
+ running: running,
364
+ enabled: enabled,
365
+ type: 'upstart',
366
+ }
367
+ end
368
+
369
+ private
370
+
371
+ def info_enabled(service_name)
372
+ # check if a service is enabled
373
+ config = read_file_content("/etc/init/#{service_name}.conf", allow_empty: true)
374
+
375
+ !config.match(/^\s*start on/).nil?
376
+ end
377
+
378
+ def version
379
+ @version ||= begin
380
+ out = inspec.command("#{service_ctl} --version").stdout
381
+ Gem::Version.new(out[/\(upstart ([^\)]+)\)/, 1])
382
+ end
383
+ end
384
+ end
385
+
386
+ class SysV < ServiceManager
387
+ RUNLEVELS = { 0=>false, 1=>false, 2=>false, 3=>false, 4=>false, 5=>false, 6=>false }.freeze
388
+
389
+ def initialize(service_name, service_ctl = nil)
390
+ @service_ctl = service_ctl || 'service'
391
+ super
392
+ end
393
+
394
+ def info(service_name)
395
+ # check if service is installed
396
+ # read all available services via ls /etc/init.d/
397
+ srvlist = inspec.command('ls -1 /etc/init.d/')
398
+ return nil if srvlist.exit_status != 0
399
+
400
+ # check if the service is in list
401
+ service = srvlist.stdout.split("\n").select { |srv| srv == service_name }
402
+
403
+ # abort if we could not find any service
404
+ return nil if service.empty?
405
+
406
+ # read all enabled services from runlevel
407
+ # on rhel via: 'chkconfig --list', is not installed by default
408
+ # bash: for i in `find /etc/rc*.d -name S*`; do basename $i | sed -r 's/^S[0-9]+//'; done | sort | uniq
409
+ enabled_services_cmd = inspec.command('find /etc/rc*.d /etc/init.d/rc*.d -name "S*"').stdout
410
+ service_line = %r{rc(?<runlevel>[0-6])\.d/S[^/]*?#{Regexp.escape service_name}$}
411
+ all_services = enabled_services_cmd.split("\n").map { |line|
412
+ service_line.match(line)
413
+ }.compact
414
+ enabled = !all_services.empty?
415
+
416
+ # Determine a list of runlevels which this service is activated for
417
+ runlevels = RUNLEVELS.dup
418
+ all_services.each { |x| runlevels[x[:runlevel].to_i] = true }
419
+
420
+ # check if service is really running
421
+ # service throws an exit code if the service is not installed or
422
+ # not enabled
423
+
424
+ cmd = inspec.command("#{service_ctl} #{service_name} status")
425
+ running = cmd.exit_status == 0
426
+ {
427
+ name: service_name,
428
+ description: nil,
429
+ installed: true,
430
+ running: running,
431
+ enabled: enabled,
432
+ runlevels: runlevels,
433
+ type: 'sysv',
434
+ }
435
+ end
436
+ end
437
+
438
+ # @see: https://www.freebsd.org/doc/en/articles/linux-users/startup.html
439
+ # @see: https://www.freebsd.org/cgi/man.cgi?query=rc.conf&sektion=5
440
+ class BSDInit < ServiceManager
441
+ def initialize(service_name, service_ctl = nil)
442
+ @service_ctl = service_ctl || 'service'
443
+ super
444
+ end
445
+
446
+ def info(service_name)
447
+ # check if service is enabled
448
+ # services are enabled in /etc/rc.conf and /etc/defaults/rc.conf
449
+ # via #{service_name}_enable="YES"
450
+ # service SERVICE status returns the following result if not activated:
451
+ # Cannot 'status' sshd. Set sshd_enable to YES in /etc/rc.conf or use 'onestatus' instead of 'status'.
452
+ # gather all enabled services
453
+ cmd = inspec.command("#{service_ctl} -e")
454
+ return nil if cmd.exit_status != 0
455
+
456
+ # search for the service
457
+ srv = /(^.*#{service_name}$)/.match(cmd.stdout)
458
+ return nil if srv.nil? || srv[0].nil?
459
+ enabled = true
460
+
461
+ # check if the service is running
462
+ # if the service is not available or not running, we always get an error code
463
+ cmd = inspec.command("#{service_ctl} #{service_name} onestatus")
464
+ running = cmd.exit_status == 0
465
+
466
+ {
467
+ name: service_name,
468
+ description: nil,
469
+ installed: true,
470
+ running: running,
471
+ enabled: enabled,
472
+ type: 'bsd-init',
473
+ }
474
+ end
475
+ end
476
+
477
+ class Runit < ServiceManager
478
+ def initialize(service_name, service_ctl = nil)
479
+ @service_ctl = service_ctl || 'sv'
480
+ super
481
+ end
482
+
483
+ # rubocop:disable Style/DoubleNegation
484
+ def info(service_name)
485
+ # get the status of runit service
486
+ cmd = inspec.command("#{service_ctl} status #{service_name}")
487
+ # return nil unless cmd.exit_status == 0 # NOTE(sr) why do we do this?
488
+
489
+ installed = cmd.exit_status == 0
490
+ running = installed && !!(cmd.stdout =~ /^run:/)
491
+ enabled = installed && (running || !!(cmd.stdout =~ /normally up/) || !!(cmd.stdout =~ /want up/))
492
+
493
+ {
494
+ name: service_name,
495
+ description: nil,
496
+ installed: installed,
497
+ running: running,
498
+ enabled: enabled,
499
+ type: 'runit',
500
+ }
501
+ end
502
+ end
503
+
504
+ # MacOS / Darwin
505
+ # new launctl on macos 10.10
506
+ class LaunchCtl < ServiceManager
507
+ def initialize(service_name, service_ctl = nil)
508
+ @service_ctl = service_ctl || 'launchctl'
509
+ super
510
+ end
511
+
512
+ def info(service_name)
513
+ # get the status of upstart service
514
+ cmd = inspec.command("#{service_ctl} list")
515
+ return nil if cmd.exit_status != 0
516
+
517
+ # search for the service
518
+ srv = /(^.*#{service_name}.*)/.match(cmd.stdout)
519
+ return nil if srv.nil? || srv[0].nil?
520
+
521
+ # extract values from service
522
+ parsed_srv = /^(?<pid>[0-9-]+)\t(?<exit>[0-9]+)\t(?<name>\S*)$/.match(srv[0])
523
+ enabled = !parsed_srv['name'].nil? # it's in the list
524
+
525
+ # check if the service is running
526
+ pid = parsed_srv['pid']
527
+ running = pid != '-'
528
+
529
+ # extract service label
530
+ srv = parsed_srv['name'] || service_name
531
+
532
+ {
533
+ name: srv,
534
+ description: nil,
535
+ installed: true,
536
+ running: running,
537
+ enabled: enabled,
538
+ type: 'darwin',
539
+ }
540
+ end
541
+ end
542
+
543
+ # Determine the service state from Windows
544
+ # Uses Powershell to retrieve the information
545
+ class WindowsSrv < ServiceManager
546
+ # Determine service details
547
+ # PS: Get-Service -Name 'dhcp'| Select-Object -Property Name, DisplayName, Status | ConvertTo-Json
548
+ # {
549
+ # "Name": "dhcp",
550
+ # "DisplayName": "DHCP Client",
551
+ # "Status": 4
552
+ # }
553
+ #
554
+ # Until StartMode is not added to Get-Service, we need to do a workaround
555
+ # @see: https://connect.microsoft.com/PowerShell/feedback/details/424948/i-would-like-to-see-the-property-starttype-added-to-get-services
556
+ # Also see: https://msdn.microsoft.com/en-us/library/aa384896(v=vs.85).aspx
557
+ # Use the following powershell to determine the start mode
558
+ # PS: Get-WmiObject -Class Win32_Service | Where-Object {$_.Name -eq $name -or $_.DisplayName -eq $name} | Select-Object -Prop
559
+ # erty Name, StartMode, State, Status | ConvertTo-Json
560
+ # {
561
+ # "Name": "Dhcp",
562
+ # "StartMode": "Auto",
563
+ # "State": "Running",
564
+ # "Status": "OK"
565
+ # }
566
+ #
567
+ # Windows Services have the following status code:
568
+ # @see: https://msdn.microsoft.com/en-us/library/windows/desktop/ms685996(v=vs.85).aspx
569
+ # - 1: Stopped
570
+ # - 2: Starting
571
+ # - 3: Stopping
572
+ # - 4: Running
573
+ # - 5: Continue Pending
574
+ # - 6: Pause Pending
575
+ # - 7: Paused
576
+ def info(service_name)
577
+ 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")
578
+
579
+ # cannot rely on exit code for now, successful command returns exit code 1
580
+ # return nil if cmd.exit_status != 0
581
+ # try to parse json
582
+ begin
583
+ service = JSON.parse(cmd.stdout)
584
+ rescue JSON::ParserError => _e
585
+ return nil
586
+ end
587
+
588
+ # check that we got a response
589
+ return nil if service.nil? || service['Service'].nil?
590
+
591
+ {
592
+ name: service['Service']['Name'],
593
+ description: service['Service']['DisplayName'],
594
+ installed: true,
595
+ running: service_running?(service),
596
+ enabled: service_enabled?(service),
597
+ startmode: service['WMI']['StartMode'],
598
+ type: 'windows',
599
+ }
600
+ end
601
+
602
+ private
603
+
604
+ # detect if service is enabled
605
+ def service_enabled?(service)
606
+ !service['WMI'].nil? &&
607
+ !service['WMI']['StartMode'].nil? &&
608
+ (service['WMI']['StartMode'] == 'Auto' ||
609
+ service['WMI']['StartMode'] == 'Manual')
610
+ end
611
+
612
+ # detect if service is running
613
+ def service_running?(service)
614
+ !service['Service']['Status'].nil? && service['Service']['Status'] == 4
615
+ end
616
+ end
617
+
618
+ # Solaris services
619
+ class Svcs < ServiceManager
620
+ def initialize(service_name, service_ctl = nil)
621
+ @service_ctl = service_ctl || 'svcs'
622
+ super
623
+ end
624
+
625
+ def info(service_name)
626
+ # get the status of runit service
627
+ cmd = inspec.command("#{service_ctl} -l #{service_name}")
628
+ return nil if cmd.exit_status != 0
629
+
630
+ params = SimpleConfig.new(
631
+ cmd.stdout.chomp,
632
+ assignment_regex: /^(\w+)\s*(.*)$/,
633
+ multiple_values: false,
634
+ ).params
635
+
636
+ installed = cmd.exit_status == 0
637
+ running = installed && (params['state'] == 'online')
638
+ enabled = installed && (params['enabled'] == 'true')
639
+
640
+ {
641
+ name: service_name,
642
+ description: params['name'],
643
+ installed: installed,
644
+ running: running,
645
+ enabled: enabled,
646
+ type: 'svcs',
647
+ }
648
+ end
649
+ end
650
+
651
+ # specific resources for specific service managers
652
+
653
+ class SystemdService < Service
654
+ name 'systemd_service'
655
+ supports platform: 'unix'
656
+ desc 'Use the systemd_service InSpec audit resource to test if the named service (controlled by systemd) is installed, running and/or enabled.'
657
+ example "
658
+ # to override service mgmt auto-detection
659
+ describe systemd_service('service_name') do
660
+ it { should be_installed }
661
+ it { should be_enabled }
662
+ it { should be_running }
663
+ end
664
+
665
+ # to set a non-standard systemctl path
666
+ describe systemd_service('service_name', '/path/to/systemctl') do
667
+ it { should be_running }
668
+ end
669
+ "
670
+
671
+ def select_service_mgmt
672
+ Systemd.new(inspec, service_ctl)
673
+ end
674
+ end
675
+
676
+ class UpstartService < Service
677
+ name 'upstart_service'
678
+ supports platform: 'unix'
679
+ desc 'Use the upstart_service InSpec audit resource to test if the named service (controlled by upstart) is installed, running and/or enabled.'
680
+ example "
681
+ # to override service mgmt auto-detection
682
+ describe upstart_service('service_name') do
683
+ it { should be_installed }
684
+ it { should be_enabled }
685
+ it { should be_running }
686
+ end
687
+
688
+ # to set a non-standard initctl path
689
+ describe upstart_service('service_name', '/path/to/initctl') do
690
+ it { should be_running }
691
+ end
692
+ "
693
+
694
+ def select_service_mgmt
695
+ Upstart.new(inspec, service_ctl)
696
+ end
697
+ end
698
+
699
+ class SysVService < Service
700
+ name 'sysv_service'
701
+ supports platform: 'unix'
702
+ desc 'Use the sysv_service InSpec audit resource to test if the named service (controlled by SysV) is installed, running and/or enabled.'
703
+ example "
704
+ # to override service mgmt auto-detection
705
+ describe sysv_service('service_name') do
706
+ it { should be_installed }
707
+ it { should be_enabled }
708
+ it { should be_running }
709
+ end
710
+
711
+ # to set a non-standard service path
712
+ describe sysv_service('service_name', '/path/to/service') do
713
+ it { should be_running }
714
+ end
715
+ "
716
+
717
+ def select_service_mgmt
718
+ SysV.new(inspec, service_ctl)
719
+ end
720
+ end
721
+
722
+ class BSDService < Service
723
+ name 'bsd_service'
724
+ supports platform: 'unix'
725
+ desc 'Use the bsd_service InSpec audit resource to test if the named service (controlled by BSD init) is installed, running and/or enabled.'
726
+ example "
727
+ # to override service mgmt auto-detection
728
+ describe bsd_service('service_name') do
729
+ it { should be_installed }
730
+ it { should be_enabled }
731
+ it { should be_running }
732
+ end
733
+
734
+ # to set a non-standard service path
735
+ describe bsd_service('service_name', '/path/to/service') do
736
+ it { should be_running }
737
+ end
738
+ "
739
+
740
+ def select_service_mgmt
741
+ BSDInit.new(inspec, service_ctl)
742
+ end
743
+ end
744
+
745
+ class LaunchdService < Service
746
+ name 'launchd_service'
747
+ supports platform: 'unix'
748
+ desc 'Use the launchd_service InSpec audit resource to test if the named service (controlled by launchd) is installed, running and/or enabled.'
749
+ example "
750
+ # to override service mgmt auto-detection
751
+ describe launchd_service('service_name') do
752
+ it { should be_installed }
753
+ it { should be_enabled }
754
+ it { should be_running }
755
+ end
756
+
757
+ # to set a non-standard launchctl path
758
+ describe launchd_service('service_name', '/path/to/launchctl') do
759
+ it { should be_running }
760
+ end
761
+ "
762
+
763
+ def select_service_mgmt
764
+ LaunchCtl.new(inspec, service_ctl)
765
+ end
766
+ end
767
+
768
+ class RunitService < Service
769
+ name 'runit_service'
770
+ supports platform: 'unix'
771
+ desc 'Use the runit_service InSpec audit resource to test if the named service (controlled by runit) is installed, running and/or enabled.'
772
+ example "
773
+ # to override service mgmt auto-detection
774
+ describe runit_service('service_name') do
775
+ it { should be_installed }
776
+ it { should be_enabled }
777
+ it { should be_running }
778
+ end
779
+
780
+ # to set a non-standard sv path
781
+ describe runit_service('service_name', '/path/to/sv') do
782
+ it { should be_running }
783
+ end
784
+ "
785
+
786
+ def select_service_mgmt
787
+ Runit.new(inspec, service_ctl)
788
+ end
789
+ end
790
+ end