inspec 2.0.16 → 2.0.17

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 (480) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +101 -101
  3. data/CHANGELOG.md +2949 -2944
  4. data/Gemfile +55 -55
  5. data/LICENSE +14 -14
  6. data/MAINTAINERS.md +31 -31
  7. data/MAINTAINERS.toml +47 -47
  8. data/README.md +438 -438
  9. data/Rakefile +284 -284
  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 +93 -93
  15. data/docs/glossary.md +99 -99
  16. data/docs/habitat.md +191 -191
  17. data/docs/inspec_and_friends.md +107 -107
  18. data/docs/matchers.md +165 -165
  19. data/docs/migration.md +293 -293
  20. data/docs/platforms.md +118 -118
  21. data/docs/plugin_kitchen_inspec.md +49 -49
  22. data/docs/profiles.md +370 -370
  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_ec2_instance.md.erb +106 -106
  36. data/docs/resources/aws_iam_access_key.md.erb +123 -123
  37. data/docs/resources/aws_iam_access_keys.md.erb +198 -198
  38. data/docs/resources/aws_iam_group.md.erb +46 -46
  39. data/docs/resources/aws_iam_groups.md.erb +43 -43
  40. data/docs/resources/aws_iam_password_policy.md.erb +76 -76
  41. data/docs/resources/aws_iam_policies.md.erb +82 -82
  42. data/docs/resources/aws_iam_policy.md.erb +146 -146
  43. data/docs/resources/aws_iam_role.md.erb +65 -65
  44. data/docs/resources/aws_iam_root_user.md.erb +58 -58
  45. data/docs/resources/aws_iam_user.md.erb +64 -64
  46. data/docs/resources/aws_iam_users.md.erb +89 -89
  47. data/docs/resources/aws_kms_keys.md.erb +84 -84
  48. data/docs/resources/aws_route_table.md.erb +47 -47
  49. data/docs/resources/aws_s3_bucket.md.erb +134 -134
  50. data/docs/resources/aws_security_group.md.erb +152 -152
  51. data/docs/resources/aws_security_groups.md.erb +92 -92
  52. data/docs/resources/aws_sns_topic.md.erb +62 -62
  53. data/docs/resources/aws_subnet.md.erb +133 -133
  54. data/docs/resources/aws_subnets.md.erb +126 -126
  55. data/docs/resources/aws_vpc.md.erb +120 -120
  56. data/docs/resources/aws_vpcs.md.erb +48 -48
  57. data/docs/resources/azure_generic_resource.md.erb +170 -139
  58. data/docs/resources/azure_resource_group.md.erb +284 -284
  59. data/docs/resources/azure_virtual_machine.md.erb +347 -314
  60. data/docs/resources/azure_virtual_machine_data_disk.md.erb +224 -182
  61. data/docs/resources/bash.md.erb +75 -75
  62. data/docs/resources/bond.md.erb +90 -90
  63. data/docs/resources/bridge.md.erb +57 -57
  64. data/docs/resources/bsd_service.md.erb +67 -67
  65. data/docs/resources/command.md.erb +138 -138
  66. data/docs/resources/cpan.md.erb +79 -79
  67. data/docs/resources/cran.md.erb +64 -64
  68. data/docs/resources/crontab.md.erb +88 -88
  69. data/docs/resources/csv.md.erb +54 -54
  70. data/docs/resources/dh_params.md.erb +217 -217
  71. data/docs/resources/directory.md.erb +30 -30
  72. data/docs/resources/docker.md.erb +164 -164
  73. data/docs/resources/docker_container.md.erb +104 -104
  74. data/docs/resources/docker_image.md.erb +94 -94
  75. data/docs/resources/docker_service.md.erb +114 -114
  76. data/docs/resources/elasticsearch.md.erb +242 -242
  77. data/docs/resources/etc_fstab.md.erb +125 -125
  78. data/docs/resources/etc_group.md.erb +75 -75
  79. data/docs/resources/etc_hosts.md.erb +78 -78
  80. data/docs/resources/etc_hosts_allow.md.erb +74 -74
  81. data/docs/resources/etc_hosts_deny.md.erb +74 -74
  82. data/docs/resources/file.md.erb +515 -515
  83. data/docs/resources/filesystem.md.erb +41 -41
  84. data/docs/resources/firewalld.md.erb +107 -107
  85. data/docs/resources/gem.md.erb +79 -79
  86. data/docs/resources/group.md.erb +61 -61
  87. data/docs/resources/grub_conf.md.erb +101 -101
  88. data/docs/resources/host.md.erb +78 -78
  89. data/docs/resources/http.md.erb +101 -101
  90. data/docs/resources/iis_app.md.erb +122 -122
  91. data/docs/resources/iis_site.md.erb +135 -135
  92. data/docs/resources/inetd_conf.md.erb +94 -94
  93. data/docs/resources/ini.md.erb +76 -76
  94. data/docs/resources/interface.md.erb +58 -58
  95. data/docs/resources/iptables.md.erb +64 -64
  96. data/docs/resources/json.md.erb +62 -62
  97. data/docs/resources/kernel_module.md.erb +107 -107
  98. data/docs/resources/kernel_parameter.md.erb +53 -53
  99. data/docs/resources/key_rsa.md.erb +85 -85
  100. data/docs/resources/launchd_service.md.erb +57 -57
  101. data/docs/resources/limits_conf.md.erb +75 -75
  102. data/docs/resources/login_def.md.erb +71 -71
  103. data/docs/resources/mount.md.erb +69 -69
  104. data/docs/resources/mssql_session.md.erb +60 -60
  105. data/docs/resources/mysql_conf.md.erb +99 -99
  106. data/docs/resources/mysql_session.md.erb +74 -74
  107. data/docs/resources/nginx.md.erb +79 -79
  108. data/docs/resources/nginx_conf.md.erb +128 -128
  109. data/docs/resources/npm.md.erb +60 -60
  110. data/docs/resources/ntp_conf.md.erb +60 -60
  111. data/docs/resources/oneget.md.erb +53 -53
  112. data/docs/resources/oracledb_session.md.erb +52 -52
  113. data/docs/resources/os.md.erb +141 -141
  114. data/docs/resources/os_env.md.erb +78 -78
  115. data/docs/resources/package.md.erb +120 -120
  116. data/docs/resources/packages.md.erb +67 -67
  117. data/docs/resources/parse_config.md.erb +103 -103
  118. data/docs/resources/parse_config_file.md.erb +138 -138
  119. data/docs/resources/passwd.md.erb +141 -141
  120. data/docs/resources/pip.md.erb +67 -67
  121. data/docs/resources/port.md.erb +137 -137
  122. data/docs/resources/postgres_conf.md.erb +79 -79
  123. data/docs/resources/postgres_hba_conf.md.erb +93 -93
  124. data/docs/resources/postgres_ident_conf.md.erb +76 -76
  125. data/docs/resources/postgres_session.md.erb +69 -69
  126. data/docs/resources/powershell.md.erb +102 -102
  127. data/docs/resources/processes.md.erb +109 -109
  128. data/docs/resources/rabbitmq_config.md.erb +41 -41
  129. data/docs/resources/registry_key.md.erb +158 -158
  130. data/docs/resources/runit_service.md.erb +57 -57
  131. data/docs/resources/security_policy.md.erb +47 -47
  132. data/docs/resources/service.md.erb +121 -121
  133. data/docs/resources/shadow.md.erb +144 -144
  134. data/docs/resources/ssh_config.md.erb +80 -80
  135. data/docs/resources/sshd_config.md.erb +83 -83
  136. data/docs/resources/ssl.md.erb +119 -119
  137. data/docs/resources/sys_info.md.erb +42 -42
  138. data/docs/resources/systemd_service.md.erb +57 -57
  139. data/docs/resources/sysv_service.md.erb +57 -57
  140. data/docs/resources/upstart_service.md.erb +57 -57
  141. data/docs/resources/user.md.erb +140 -140
  142. data/docs/resources/users.md.erb +127 -127
  143. data/docs/resources/vbscript.md.erb +55 -55
  144. data/docs/resources/virtualization.md.erb +57 -57
  145. data/docs/resources/windows_feature.md.erb +47 -47
  146. data/docs/resources/windows_hotfix.md.erb +53 -53
  147. data/docs/resources/windows_task.md.erb +95 -95
  148. data/docs/resources/wmi.md.erb +81 -81
  149. data/docs/resources/x509_certificate.md.erb +151 -151
  150. data/docs/resources/xinetd_conf.md.erb +156 -156
  151. data/docs/resources/xml.md.erb +85 -85
  152. data/docs/resources/yaml.md.erb +69 -69
  153. data/docs/resources/yum.md.erb +98 -98
  154. data/docs/resources/zfs_dataset.md.erb +53 -53
  155. data/docs/resources/zfs_pool.md.erb +47 -47
  156. data/docs/ruby_usage.md +203 -203
  157. data/docs/shared/matcher_be.md.erb +1 -1
  158. data/docs/shared/matcher_cmp.md.erb +43 -43
  159. data/docs/shared/matcher_eq.md.erb +3 -3
  160. data/docs/shared/matcher_include.md.erb +1 -1
  161. data/docs/shared/matcher_match.md.erb +1 -1
  162. data/docs/shell.md +172 -172
  163. data/examples/README.md +8 -8
  164. data/examples/inheritance/README.md +65 -65
  165. data/examples/inheritance/controls/example.rb +14 -14
  166. data/examples/inheritance/inspec.yml +15 -15
  167. data/examples/kitchen-ansible/.kitchen.yml +25 -25
  168. data/examples/kitchen-ansible/Gemfile +19 -19
  169. data/examples/kitchen-ansible/README.md +53 -53
  170. data/examples/kitchen-ansible/files/nginx.repo +6 -6
  171. data/examples/kitchen-ansible/tasks/main.yml +16 -16
  172. data/examples/kitchen-ansible/test/integration/default/default.yml +5 -5
  173. data/examples/kitchen-ansible/test/integration/default/web_spec.rb +28 -28
  174. data/examples/kitchen-chef/.kitchen.yml +20 -20
  175. data/examples/kitchen-chef/Berksfile +3 -3
  176. data/examples/kitchen-chef/Gemfile +19 -19
  177. data/examples/kitchen-chef/README.md +27 -27
  178. data/examples/kitchen-chef/metadata.rb +7 -7
  179. data/examples/kitchen-chef/recipes/default.rb +6 -6
  180. data/examples/kitchen-chef/recipes/nginx.rb +30 -30
  181. data/examples/kitchen-chef/test/integration/default/web_spec.rb +28 -28
  182. data/examples/kitchen-puppet/.kitchen.yml +22 -22
  183. data/examples/kitchen-puppet/Gemfile +20 -20
  184. data/examples/kitchen-puppet/Puppetfile +25 -25
  185. data/examples/kitchen-puppet/README.md +53 -53
  186. data/examples/kitchen-puppet/manifests/site.pp +33 -33
  187. data/examples/kitchen-puppet/metadata.json +11 -11
  188. data/examples/kitchen-puppet/test/integration/default/web_spec.rb +28 -28
  189. data/examples/meta-profile/README.md +37 -37
  190. data/examples/meta-profile/controls/example.rb +13 -13
  191. data/examples/meta-profile/inspec.yml +13 -13
  192. data/examples/profile-attribute.yml +2 -2
  193. data/examples/profile-attribute/README.md +14 -14
  194. data/examples/profile-attribute/controls/example.rb +11 -11
  195. data/examples/profile-attribute/inspec.yml +8 -8
  196. data/examples/profile-aws/controls/iam_password_policy_expiration.rb +8 -8
  197. data/examples/profile-aws/controls/iam_password_policy_max_age.rb +8 -8
  198. data/examples/profile-aws/controls/iam_root_user_mfa.rb +8 -8
  199. data/examples/profile-aws/controls/iam_users_access_key_age.rb +8 -8
  200. data/examples/profile-aws/controls/iam_users_console_users_mfa.rb +8 -8
  201. data/examples/profile-aws/inspec.yml +11 -11
  202. data/examples/profile-azure/controls/azure_resource_group_example.rb +24 -24
  203. data/examples/profile-azure/controls/azure_vm_example.rb +29 -29
  204. data/examples/profile-azure/inspec.yml +11 -11
  205. data/examples/profile-sensitive/README.md +29 -29
  206. data/examples/profile-sensitive/controls/sensitive-failures.rb +9 -9
  207. data/examples/profile-sensitive/controls/sensitive.rb +9 -9
  208. data/examples/profile-sensitive/inspec.yml +8 -8
  209. data/examples/profile/README.md +48 -48
  210. data/examples/profile/controls/example.rb +23 -23
  211. data/examples/profile/controls/gordon.rb +36 -36
  212. data/examples/profile/controls/meta.rb +34 -34
  213. data/examples/profile/inspec.yml +10 -10
  214. data/examples/profile/libraries/gordon_config.rb +53 -53
  215. data/inspec.gemspec +47 -47
  216. data/lib/bundles/README.md +3 -3
  217. data/lib/bundles/inspec-artifact.rb +7 -7
  218. data/lib/bundles/inspec-artifact/README.md +1 -1
  219. data/lib/bundles/inspec-artifact/cli.rb +277 -277
  220. data/lib/bundles/inspec-compliance.rb +16 -16
  221. data/lib/bundles/inspec-compliance/.kitchen.yml +20 -20
  222. data/lib/bundles/inspec-compliance/README.md +185 -185
  223. data/lib/bundles/inspec-compliance/api.rb +316 -316
  224. data/lib/bundles/inspec-compliance/api/login.rb +152 -152
  225. data/lib/bundles/inspec-compliance/bootstrap.sh +41 -41
  226. data/lib/bundles/inspec-compliance/cli.rb +254 -254
  227. data/lib/bundles/inspec-compliance/configuration.rb +103 -103
  228. data/lib/bundles/inspec-compliance/http.rb +86 -86
  229. data/lib/bundles/inspec-compliance/support.rb +36 -36
  230. data/lib/bundles/inspec-compliance/target.rb +98 -98
  231. data/lib/bundles/inspec-compliance/test/integration/default/cli.rb +93 -93
  232. data/lib/bundles/inspec-habitat.rb +12 -12
  233. data/lib/bundles/inspec-habitat/cli.rb +36 -36
  234. data/lib/bundles/inspec-habitat/log.rb +10 -10
  235. data/lib/bundles/inspec-habitat/profile.rb +390 -390
  236. data/lib/bundles/inspec-init.rb +8 -8
  237. data/lib/bundles/inspec-init/README.md +31 -31
  238. data/lib/bundles/inspec-init/cli.rb +97 -97
  239. data/lib/bundles/inspec-init/templates/profile/README.md +3 -3
  240. data/lib/bundles/inspec-init/templates/profile/controls/example.rb +19 -19
  241. data/lib/bundles/inspec-init/templates/profile/inspec.yml +8 -8
  242. data/lib/bundles/inspec-supermarket.rb +13 -13
  243. data/lib/bundles/inspec-supermarket/README.md +45 -45
  244. data/lib/bundles/inspec-supermarket/api.rb +84 -84
  245. data/lib/bundles/inspec-supermarket/cli.rb +73 -73
  246. data/lib/bundles/inspec-supermarket/target.rb +34 -34
  247. data/lib/fetchers/git.rb +163 -163
  248. data/lib/fetchers/local.rb +74 -74
  249. data/lib/fetchers/mock.rb +35 -35
  250. data/lib/fetchers/url.rb +204 -204
  251. data/lib/inspec.rb +24 -24
  252. data/lib/inspec/archive/tar.rb +29 -29
  253. data/lib/inspec/archive/zip.rb +19 -19
  254. data/lib/inspec/backend.rb +92 -92
  255. data/lib/inspec/base_cli.rb +350 -333
  256. data/lib/inspec/cached_fetcher.rb +66 -66
  257. data/lib/inspec/cli.rb +292 -302
  258. data/lib/inspec/completions/bash.sh.erb +45 -45
  259. data/lib/inspec/completions/fish.sh.erb +34 -34
  260. data/lib/inspec/completions/zsh.sh.erb +61 -61
  261. data/lib/inspec/control_eval_context.rb +179 -179
  262. data/lib/inspec/dependencies/cache.rb +72 -72
  263. data/lib/inspec/dependencies/dependency_set.rb +92 -92
  264. data/lib/inspec/dependencies/lockfile.rb +115 -115
  265. data/lib/inspec/dependencies/requirement.rb +123 -123
  266. data/lib/inspec/dependencies/resolver.rb +86 -86
  267. data/lib/inspec/describe.rb +27 -27
  268. data/lib/inspec/dsl.rb +66 -66
  269. data/lib/inspec/dsl_shared.rb +33 -33
  270. data/lib/inspec/env_printer.rb +157 -157
  271. data/lib/inspec/errors.rb +13 -13
  272. data/lib/inspec/exceptions.rb +12 -12
  273. data/lib/inspec/expect.rb +45 -45
  274. data/lib/inspec/fetcher.rb +45 -45
  275. data/lib/inspec/file_provider.rb +275 -275
  276. data/lib/inspec/formatters.rb +3 -3
  277. data/lib/inspec/formatters/base.rb +250 -250
  278. data/lib/inspec/formatters/json_rspec.rb +20 -20
  279. data/lib/inspec/formatters/show_progress.rb +12 -12
  280. data/lib/inspec/library_eval_context.rb +58 -58
  281. data/lib/inspec/log.rb +11 -11
  282. data/lib/inspec/metadata.rb +247 -247
  283. data/lib/inspec/method_source.rb +24 -24
  284. data/lib/inspec/objects.rb +14 -14
  285. data/lib/inspec/objects/attribute.rb +65 -65
  286. data/lib/inspec/objects/control.rb +61 -61
  287. data/lib/inspec/objects/describe.rb +92 -92
  288. data/lib/inspec/objects/each_loop.rb +36 -36
  289. data/lib/inspec/objects/list.rb +15 -15
  290. data/lib/inspec/objects/or_test.rb +40 -40
  291. data/lib/inspec/objects/ruby_helper.rb +15 -15
  292. data/lib/inspec/objects/tag.rb +27 -27
  293. data/lib/inspec/objects/test.rb +87 -87
  294. data/lib/inspec/objects/value.rb +27 -27
  295. data/lib/inspec/plugins.rb +60 -60
  296. data/lib/inspec/plugins/cli.rb +24 -24
  297. data/lib/inspec/plugins/fetcher.rb +86 -86
  298. data/lib/inspec/plugins/resource.rb +133 -133
  299. data/lib/inspec/plugins/secret.rb +15 -15
  300. data/lib/inspec/plugins/source_reader.rb +40 -40
  301. data/lib/inspec/polyfill.rb +12 -12
  302. data/lib/inspec/profile.rb +510 -510
  303. data/lib/inspec/profile_context.rb +207 -207
  304. data/lib/inspec/profile_vendor.rb +66 -66
  305. data/lib/inspec/reporters.rb +50 -50
  306. data/lib/inspec/reporters/base.rb +24 -24
  307. data/lib/inspec/reporters/cli.rb +356 -356
  308. data/lib/inspec/reporters/json.rb +116 -116
  309. data/lib/inspec/reporters/json_min.rb +48 -48
  310. data/lib/inspec/reporters/junit.rb +77 -77
  311. data/lib/inspec/require_loader.rb +33 -33
  312. data/lib/inspec/resource.rb +186 -186
  313. data/lib/inspec/rule.rb +266 -266
  314. data/lib/inspec/runner.rb +344 -344
  315. data/lib/inspec/runner_mock.rb +41 -41
  316. data/lib/inspec/runner_rspec.rb +174 -174
  317. data/lib/inspec/runtime_profile.rb +26 -26
  318. data/lib/inspec/schema.rb +213 -213
  319. data/lib/inspec/secrets.rb +19 -19
  320. data/lib/inspec/secrets/yaml.rb +30 -30
  321. data/lib/inspec/shell.rb +220 -223
  322. data/lib/inspec/shell_detector.rb +90 -90
  323. data/lib/inspec/source_reader.rb +29 -29
  324. data/lib/inspec/version.rb +8 -8
  325. data/lib/matchers/matchers.rb +339 -339
  326. data/lib/resource_support/aws.rb +40 -40
  327. data/lib/resource_support/aws/aws_backend_base.rb +12 -12
  328. data/lib/resource_support/aws/aws_backend_factory_mixin.rb +12 -12
  329. data/lib/resource_support/aws/aws_plural_resource_mixin.rb +21 -21
  330. data/lib/resource_support/aws/aws_resource_mixin.rb +66 -66
  331. data/lib/resource_support/aws/aws_singular_resource_mixin.rb +24 -24
  332. data/lib/resources/aide_conf.rb +160 -160
  333. data/lib/resources/apache.rb +48 -48
  334. data/lib/resources/apache_conf.rb +156 -156
  335. data/lib/resources/apt.rb +149 -149
  336. data/lib/resources/audit_policy.rb +63 -63
  337. data/lib/resources/auditd.rb +231 -231
  338. data/lib/resources/auditd_conf.rb +55 -55
  339. data/lib/resources/aws/aws_cloudtrail_trail.rb +77 -77
  340. data/lib/resources/aws/aws_cloudtrail_trails.rb +47 -47
  341. data/lib/resources/aws/aws_cloudwatch_alarm.rb +62 -62
  342. data/lib/resources/aws/aws_cloudwatch_log_metric_filter.rb +100 -100
  343. data/lib/resources/aws/aws_ec2_instance.rb +157 -157
  344. data/lib/resources/aws/aws_iam_access_key.rb +106 -106
  345. data/lib/resources/aws/aws_iam_access_keys.rb +144 -144
  346. data/lib/resources/aws/aws_iam_group.rb +56 -56
  347. data/lib/resources/aws/aws_iam_groups.rb +45 -45
  348. data/lib/resources/aws/aws_iam_password_policy.rb +116 -116
  349. data/lib/resources/aws/aws_iam_policies.rb +46 -46
  350. data/lib/resources/aws/aws_iam_policy.rb +119 -119
  351. data/lib/resources/aws/aws_iam_role.rb +51 -51
  352. data/lib/resources/aws/aws_iam_root_user.rb +60 -60
  353. data/lib/resources/aws/aws_iam_user.rb +111 -111
  354. data/lib/resources/aws/aws_iam_users.rb +96 -96
  355. data/lib/resources/aws/aws_kms_keys.rb +46 -46
  356. data/lib/resources/aws/aws_route_table.rb +61 -61
  357. data/lib/resources/aws/aws_s3_bucket.rb +115 -115
  358. data/lib/resources/aws/aws_security_group.rb +93 -93
  359. data/lib/resources/aws/aws_security_groups.rb +68 -68
  360. data/lib/resources/aws/aws_sns_topic.rb +53 -53
  361. data/lib/resources/aws/aws_subnet.rb +88 -88
  362. data/lib/resources/aws/aws_subnets.rb +53 -53
  363. data/lib/resources/aws/aws_vpc.rb +69 -69
  364. data/lib/resources/aws/aws_vpcs.rb +45 -45
  365. data/lib/resources/azure/azure_backend.rb +377 -377
  366. data/lib/resources/azure/azure_generic_resource.rb +59 -59
  367. data/lib/resources/azure/azure_resource_group.rb +152 -152
  368. data/lib/resources/azure/azure_virtual_machine.rb +264 -264
  369. data/lib/resources/azure/azure_virtual_machine_data_disk.rb +136 -136
  370. data/lib/resources/bash.rb +35 -35
  371. data/lib/resources/bond.rb +68 -68
  372. data/lib/resources/bridge.rb +122 -122
  373. data/lib/resources/command.rb +69 -69
  374. data/lib/resources/cpan.rb +58 -58
  375. data/lib/resources/cran.rb +64 -64
  376. data/lib/resources/crontab.rb +170 -170
  377. data/lib/resources/csv.rb +60 -60
  378. data/lib/resources/dh_params.rb +82 -82
  379. data/lib/resources/directory.rb +25 -25
  380. data/lib/resources/docker.rb +236 -236
  381. data/lib/resources/docker_container.rb +89 -89
  382. data/lib/resources/docker_image.rb +83 -83
  383. data/lib/resources/docker_object.rb +57 -57
  384. data/lib/resources/docker_service.rb +90 -90
  385. data/lib/resources/elasticsearch.rb +169 -169
  386. data/lib/resources/etc_fstab.rb +102 -102
  387. data/lib/resources/etc_group.rb +156 -156
  388. data/lib/resources/etc_hosts.rb +81 -81
  389. data/lib/resources/etc_hosts_allow_deny.rb +123 -123
  390. data/lib/resources/file.rb +298 -298
  391. data/lib/resources/filesystem.rb +31 -31
  392. data/lib/resources/firewalld.rb +144 -144
  393. data/lib/resources/gem.rb +70 -70
  394. data/lib/resources/groups.rb +215 -215
  395. data/lib/resources/grub_conf.rb +237 -237
  396. data/lib/resources/host.rb +300 -300
  397. data/lib/resources/http.rb +250 -250
  398. data/lib/resources/iis_app.rb +104 -104
  399. data/lib/resources/iis_site.rb +148 -148
  400. data/lib/resources/inetd_conf.rb +62 -62
  401. data/lib/resources/ini.rb +29 -29
  402. data/lib/resources/interface.rb +129 -129
  403. data/lib/resources/iptables.rb +69 -69
  404. data/lib/resources/json.rb +117 -117
  405. data/lib/resources/kernel_module.rb +107 -107
  406. data/lib/resources/kernel_parameter.rb +58 -58
  407. data/lib/resources/key_rsa.rb +67 -67
  408. data/lib/resources/limits_conf.rb +55 -55
  409. data/lib/resources/login_def.rb +66 -66
  410. data/lib/resources/mount.rb +88 -88
  411. data/lib/resources/mssql_session.rb +101 -101
  412. data/lib/resources/mysql.rb +81 -81
  413. data/lib/resources/mysql_conf.rb +134 -134
  414. data/lib/resources/mysql_session.rb +71 -71
  415. data/lib/resources/nginx.rb +96 -96
  416. data/lib/resources/nginx_conf.rb +227 -227
  417. data/lib/resources/npm.rb +48 -48
  418. data/lib/resources/ntp_conf.rb +58 -58
  419. data/lib/resources/oneget.rb +71 -71
  420. data/lib/resources/oracledb_session.rb +139 -139
  421. data/lib/resources/os.rb +36 -36
  422. data/lib/resources/os_env.rb +76 -76
  423. data/lib/resources/package.rb +363 -363
  424. data/lib/resources/packages.rb +111 -111
  425. data/lib/resources/parse_config.rb +116 -116
  426. data/lib/resources/passwd.rb +74 -74
  427. data/lib/resources/pip.rb +89 -89
  428. data/lib/resources/platform.rb +109 -109
  429. data/lib/resources/port.rb +771 -771
  430. data/lib/resources/postgres.rb +130 -130
  431. data/lib/resources/postgres_conf.rb +121 -121
  432. data/lib/resources/postgres_hba_conf.rb +100 -100
  433. data/lib/resources/postgres_ident_conf.rb +78 -78
  434. data/lib/resources/postgres_session.rb +71 -71
  435. data/lib/resources/powershell.rb +57 -57
  436. data/lib/resources/processes.rb +204 -204
  437. data/lib/resources/rabbitmq_conf.rb +52 -52
  438. data/lib/resources/registry_key.rb +296 -296
  439. data/lib/resources/security_policy.rb +180 -180
  440. data/lib/resources/service.rb +789 -789
  441. data/lib/resources/shadow.rb +140 -140
  442. data/lib/resources/ssh_conf.rb +102 -102
  443. data/lib/resources/ssl.rb +99 -99
  444. data/lib/resources/sys_info.rb +28 -28
  445. data/lib/resources/toml.rb +32 -32
  446. data/lib/resources/users.rb +654 -654
  447. data/lib/resources/vbscript.rb +69 -69
  448. data/lib/resources/virtualization.rb +251 -251
  449. data/lib/resources/windows_feature.rb +84 -84
  450. data/lib/resources/windows_hotfix.rb +35 -35
  451. data/lib/resources/windows_task.rb +105 -105
  452. data/lib/resources/wmi.rb +113 -113
  453. data/lib/resources/x509_certificate.rb +143 -143
  454. data/lib/resources/xinetd.rb +111 -111
  455. data/lib/resources/xml.rb +46 -46
  456. data/lib/resources/yaml.rb +47 -47
  457. data/lib/resources/yum.rb +180 -180
  458. data/lib/resources/zfs_dataset.rb +60 -60
  459. data/lib/resources/zfs_pool.rb +49 -49
  460. data/lib/source_readers/flat.rb +39 -39
  461. data/lib/source_readers/inspec.rb +75 -75
  462. data/lib/utils/command_wrapper.rb +27 -27
  463. data/lib/utils/convert.rb +12 -12
  464. data/lib/utils/database_helpers.rb +77 -77
  465. data/lib/utils/erlang_parser.rb +192 -192
  466. data/lib/utils/filter.rb +272 -272
  467. data/lib/utils/filter_array.rb +27 -27
  468. data/lib/utils/find_files.rb +44 -44
  469. data/lib/utils/hash.rb +41 -41
  470. data/lib/utils/json_log.rb +18 -18
  471. data/lib/utils/latest_version.rb +22 -22
  472. data/lib/utils/modulator.rb +12 -12
  473. data/lib/utils/nginx_parser.rb +85 -85
  474. data/lib/utils/object_traversal.rb +49 -49
  475. data/lib/utils/parser.rb +274 -274
  476. data/lib/utils/plugin_registry.rb +93 -93
  477. data/lib/utils/simpleconfig.rb +120 -120
  478. data/lib/utils/spdx.rb +13 -13
  479. data/lib/utils/spdx.txt +343 -343
  480. metadata +1 -1
@@ -1,36 +1,36 @@
1
- # encoding: utf-8
2
-
3
- require 'resources/platform'
4
-
5
- module Inspec::Resources
6
- class OSResource < PlatformResource
7
- name 'os'
8
- supports platform: 'unix'
9
- supports platform: 'windows'
10
- desc 'Use the os InSpec audit resource to test the platform on which the system is running.'
11
- example "
12
- describe os[:family] do
13
- it { should eq 'redhat' }
14
- end
15
-
16
- describe os.redhat? do
17
- it { should eq true }
18
- end
19
-
20
- describe os.linux? do
21
- it { should eq true }
22
- end
23
- "
24
-
25
- # reuse helper methods from backend
26
- %w{aix? redhat? debian? suse? bsd? solaris? linux? unix? windows? hpux? darwin?}.each do |os_family|
27
- define_method(os_family.to_sym) do
28
- @platform.send(os_family)
29
- end
30
- end
31
-
32
- def to_s
33
- 'Operating System Detection'
34
- end
35
- end
36
- end
1
+ # encoding: utf-8
2
+
3
+ require 'resources/platform'
4
+
5
+ module Inspec::Resources
6
+ class OSResource < PlatformResource
7
+ name 'os'
8
+ supports platform: 'unix'
9
+ supports platform: 'windows'
10
+ desc 'Use the os InSpec audit resource to test the platform on which the system is running.'
11
+ example "
12
+ describe os[:family] do
13
+ it { should eq 'redhat' }
14
+ end
15
+
16
+ describe os.redhat? do
17
+ it { should eq true }
18
+ end
19
+
20
+ describe os.linux? do
21
+ it { should eq true }
22
+ end
23
+ "
24
+
25
+ # reuse helper methods from backend
26
+ %w{aix? redhat? debian? suse? bsd? solaris? linux? unix? windows? hpux? darwin?}.each do |os_family|
27
+ define_method(os_family.to_sym) do
28
+ @platform.send(os_family)
29
+ end
30
+ end
31
+
32
+ def to_s
33
+ 'Operating System Detection'
34
+ end
35
+ end
36
+ end
@@ -1,76 +1,76 @@
1
- # encoding: utf-8
2
- # copyright: 2015, Vulcano Security GmbH
3
-
4
- # Usage:
5
- #
6
- # describe os_env('PATH') do
7
- # its('split') { should_not include('') }
8
- # its('split') { should_not include('.') }
9
- # end
10
-
11
- require 'utils/simpleconfig'
12
-
13
- module Inspec::Resources
14
- class OsEnv < Inspec.resource(1)
15
- name 'os_env'
16
- supports platform: 'unix'
17
- supports platform: 'windows'
18
- desc 'Use the os_env InSpec audit resource to test the environment variables for the platform on which the system is running.'
19
- example "
20
- describe os_env('VARIABLE') do
21
- its('matcher') { should eq 1 }
22
- end
23
- "
24
-
25
- attr_reader :content
26
- def initialize(env = nil)
27
- @osenv = env
28
- end
29
-
30
- def split
31
- # we can't take advantage of `File::PATH_SEPARATOR` as code is
32
- # evaluated on the host machine
33
- path_separator = inspec.os.windows? ? ';' : ':'
34
- # -1 is required to catch cases like dir1::dir2:
35
- # where we have a trailing :
36
- content.nil? ? [] : content.split(path_separator, -1)
37
- end
38
-
39
- def content
40
- return @content if defined?(@content)
41
- @content = value_for(@osenv) unless @osenv.nil?
42
- end
43
-
44
- def to_s
45
- if @osenv.nil?
46
- 'Environment variables'
47
- else
48
- "Environment variable #{@osenv}"
49
- end
50
- end
51
-
52
- private
53
-
54
- def value_for(env)
55
- command = if inspec.os.windows?
56
- "${Env:#{env}}"
57
- else
58
- 'env'
59
- end
60
-
61
- out = inspec.command(command)
62
-
63
- unless out.exit_status == 0
64
- skip_resource "Can't read environment variables on #{inspec.os.name}. "\
65
- "Tried `#{command}` which returned #{out.exit_status}"
66
- end
67
-
68
- if inspec.os.windows?
69
- out.stdout.strip
70
- else
71
- params = SimpleConfig.new(out.stdout).params
72
- params[env]
73
- end
74
- end
75
- end
76
- end
1
+ # encoding: utf-8
2
+ # copyright: 2015, Vulcano Security GmbH
3
+
4
+ # Usage:
5
+ #
6
+ # describe os_env('PATH') do
7
+ # its('split') { should_not include('') }
8
+ # its('split') { should_not include('.') }
9
+ # end
10
+
11
+ require 'utils/simpleconfig'
12
+
13
+ module Inspec::Resources
14
+ class OsEnv < Inspec.resource(1)
15
+ name 'os_env'
16
+ supports platform: 'unix'
17
+ supports platform: 'windows'
18
+ desc 'Use the os_env InSpec audit resource to test the environment variables for the platform on which the system is running.'
19
+ example "
20
+ describe os_env('VARIABLE') do
21
+ its('matcher') { should eq 1 }
22
+ end
23
+ "
24
+
25
+ attr_reader :content
26
+ def initialize(env = nil)
27
+ @osenv = env
28
+ end
29
+
30
+ def split
31
+ # we can't take advantage of `File::PATH_SEPARATOR` as code is
32
+ # evaluated on the host machine
33
+ path_separator = inspec.os.windows? ? ';' : ':'
34
+ # -1 is required to catch cases like dir1::dir2:
35
+ # where we have a trailing :
36
+ content.nil? ? [] : content.split(path_separator, -1)
37
+ end
38
+
39
+ def content
40
+ return @content if defined?(@content)
41
+ @content = value_for(@osenv) unless @osenv.nil?
42
+ end
43
+
44
+ def to_s
45
+ if @osenv.nil?
46
+ 'Environment variables'
47
+ else
48
+ "Environment variable #{@osenv}"
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def value_for(env)
55
+ command = if inspec.os.windows?
56
+ "${Env:#{env}}"
57
+ else
58
+ 'env'
59
+ end
60
+
61
+ out = inspec.command(command)
62
+
63
+ unless out.exit_status == 0
64
+ skip_resource "Can't read environment variables on #{inspec.os.name}. "\
65
+ "Tried `#{command}` which returned #{out.exit_status}"
66
+ end
67
+
68
+ if inspec.os.windows?
69
+ out.stdout.strip
70
+ else
71
+ params = SimpleConfig.new(out.stdout).params
72
+ params[env]
73
+ end
74
+ end
75
+ end
76
+ end
@@ -1,363 +1,363 @@
1
- # encoding: utf-8
2
-
3
- # Resource to determine package information
4
- #
5
- # Usage:
6
- # describe package('nginx') do
7
- # it { should be_installed }
8
- # end
9
- module Inspec::Resources
10
- class Package < Inspec.resource(1)
11
- name 'package'
12
- supports platform: 'unix'
13
- supports platform: 'windows'
14
- desc 'Use the package InSpec audit resource to test if the named package and/or package version is installed on the system.'
15
- example "
16
- describe package('nginx') do
17
- it { should be_installed }
18
- it { should_not be_held } # for dpkg platforms that support holding a version from being upgraded
19
- its('version') { should eq 1.9.5 }
20
- end
21
- "
22
-
23
- def initialize(package_name, opts = {}) # rubocop:disable Metrics/AbcSize
24
- @package_name = package_name
25
- @name = @package_name
26
- @cache = nil
27
- # select package manager
28
- @pkgman = nil
29
-
30
- os = inspec.os
31
- if os.debian?
32
- @pkgman = Deb.new(inspec)
33
- elsif os.redhat? || %w{suse amazon fedora}.include?(os[:family])
34
- @pkgman = Rpm.new(inspec, opts)
35
- elsif ['arch'].include?(os[:name])
36
- @pkgman = Pacman.new(inspec)
37
- elsif ['darwin'].include?(os[:family])
38
- @pkgman = Brew.new(inspec)
39
- elsif inspec.os.windows?
40
- @pkgman = WindowsPkg.new(inspec)
41
- elsif ['aix'].include?(os[:family])
42
- @pkgman = BffPkg.new(inspec)
43
- elsif os.solaris?
44
- @pkgman = SolarisPkg.new(inspec)
45
- elsif ['hpux'].include?(os[:family])
46
- @pkgman = HpuxPkg.new(inspec)
47
- else
48
- raise Inspec::Exceptions::ResourceSkipped, 'The `package` resource is not supported on your OS yet.'
49
- end
50
-
51
- evaluate_missing_requirements
52
- end
53
-
54
- # returns true if the package is installed
55
- def installed?(_provider = nil, _version = nil)
56
- info[:installed] == true
57
- end
58
-
59
- # returns true it the package is held (if the OS supports it)
60
- def held?(_provider = nil, _version = nil)
61
- info[:held] == true
62
- end
63
-
64
- # returns the package description
65
- def info
66
- return @cache if !@cache.nil?
67
- # All `@pkgman.info` methods return `{}`. This matches that
68
- # behavior if `@pkgman` can't be determined, thus avoiding the
69
- # `undefined method 'info' for nil:NilClass` error
70
- return {} if @pkgman.nil?
71
- @pkgman.info(@package_name)
72
- end
73
-
74
- # return the package version
75
- def version
76
- info = @pkgman.info(@package_name)
77
- info[:version]
78
- end
79
-
80
- def to_s
81
- "System Package #{@package_name}"
82
- end
83
-
84
- private
85
-
86
- def evaluate_missing_requirements
87
- missing_requirements_string = @pkgman.missing_requirements.uniq.join(', ')
88
- return if missing_requirements_string.empty?
89
- raise Inspec::Exceptions::ResourceSkipped, "The following requirements are not met for this resource: #{missing_requirements_string}"
90
- end
91
- end
92
-
93
- class PkgManagement
94
- attr_reader :inspec
95
- def initialize(inspec)
96
- @inspec = inspec
97
- end
98
-
99
- def missing_requirements
100
- # Each provider can provide an Array of missing requirements that will be
101
- # combined into a `ResourceSkipped` exception message.
102
- []
103
- end
104
- end
105
-
106
- # Debian / Ubuntu
107
- class Deb < PkgManagement
108
- def info(package_name)
109
- cmd = inspec.command("dpkg -s #{package_name}")
110
- return {} if cmd.exit_status.to_i != 0
111
-
112
- params = SimpleConfig.new(
113
- cmd.stdout.chomp,
114
- assignment_regex: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
115
- multiple_values: false,
116
- ).params
117
- # If the package is installed, Status is "install ok installed"
118
- # If the package is installed and marked hold, Status is "hold ok installed"
119
- # If the package is removed and not purged, Status is "deinstall ok config-files" with exit_status 0
120
- # If the package is purged cmd fails with non-zero exit status
121
- {
122
- name: params['Package'],
123
- installed: params['Status'].split(' ')[2] == 'installed',
124
- held: params['Status'].split(' ')[0] == 'hold',
125
- version: params['Version'],
126
- type: 'deb',
127
- }
128
- end
129
- end
130
-
131
- # RHEL family
132
- class Rpm < PkgManagement
133
- def initialize(inspec, opts)
134
- super(inspec)
135
-
136
- @dbpath = opts.fetch(:rpm_dbpath, nil)
137
- end
138
-
139
- def missing_requirements
140
- missing_requirements = []
141
-
142
- unless @dbpath.nil? || inspec.directory(@dbpath).directory?
143
- missing_requirements << "RPMDB #{@dbpath} does not exist"
144
- end
145
-
146
- missing_requirements
147
- end
148
-
149
- def info(package_name)
150
- rpm_cmd = rpm_command(package_name)
151
- cmd = inspec.command(rpm_cmd)
152
- # CentOS does not return an error code if the package is not installed,
153
- # therefore we need to check for emptyness
154
- return {} if cmd.exit_status.to_i != 0 || cmd.stdout.chomp.empty?
155
- params = SimpleConfig.new(
156
- cmd.stdout.chomp,
157
- assignment_regex: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
158
- multiple_values: false,
159
- ).params
160
- # On some (all?) systems, the linebreak before the vendor line is missing
161
- if params['Version'] =~ /\s*Vendor:/
162
- v = params['Version'].split(' ')[0]
163
- else
164
- v = params['Version']
165
- end
166
- # On some (all?) systems, the linebreak before the build line is missing
167
- if params['Release'] =~ /\s*Build Date:/
168
- r = params['Release'].split(' ')[0]
169
- else
170
- r = params['Release']
171
- end
172
- {
173
- name: params['Name'],
174
- installed: true,
175
- version: "#{v}-#{r}",
176
- type: 'rpm',
177
- }
178
- end
179
-
180
- private
181
-
182
- def rpm_command(package_name)
183
- cmd = ''
184
- cmd += 'rpm -qia'
185
- cmd += " --dbpath #{@dbpath}" if @dbpath
186
- cmd += ' ' + package_name
187
-
188
- cmd
189
- end
190
- end
191
-
192
- # MacOS / Darwin implementation
193
- class Brew < PkgManagement
194
- def info(package_name)
195
- brew_path = inspec.command('brew').exist? ? 'brew' : '/usr/local/bin/brew'
196
- cmd = inspec.command("#{brew_path} info --json=v1 #{package_name}")
197
- return {} if cmd.exit_status.to_i != 0
198
- # parse data
199
- pkg = JSON.parse(cmd.stdout)[0]
200
- {
201
- name: pkg['name'],
202
- installed: true,
203
- version: pkg['installed'][0]['version'],
204
- type: 'brew',
205
- }
206
- rescue JSON::ParserError => e
207
- raise Inspec::Exceptions::ResourceFailed,
208
- 'Failed to parse JSON from `brew` command. ' \
209
- "Error: #{e}"
210
- end
211
- end
212
-
213
- # Arch Linux
214
- class Pacman < PkgManagement
215
- def info(package_name)
216
- cmd = inspec.command("pacman -Qi #{package_name}")
217
- return {} if cmd.exit_status.to_i != 0
218
-
219
- params = SimpleConfig.new(
220
- cmd.stdout.chomp,
221
- assignment_regex: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
222
- multiple_values: false,
223
- ).params
224
-
225
- {
226
- name: params['Name'],
227
- installed: true,
228
- version: params['Version'],
229
- type: 'pacman',
230
- }
231
- end
232
- end
233
-
234
- class HpuxPkg < PkgManagement
235
- def info(package_name)
236
- cmd = inspec.command("swlist -l product | grep #{package_name}")
237
- return {} if cmd.exit_status.to_i != 0
238
- pkg = cmd.stdout.strip.split(' ')
239
- {
240
- name: pkg[0],
241
- installed: true,
242
- version: pkg[1],
243
- type: 'pkg',
244
- }
245
- end
246
- end
247
-
248
- # Determines the installed packages on Windows using the Windows package registry entries.
249
- # @see: http://blogs.technet.com/b/heyscriptingguy/archive/2013/11/15/use-powershell-to-find-installed-software.aspx
250
- class WindowsPkg < PkgManagement
251
- def info(package_name)
252
- search_paths = [
253
- 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
254
- 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
255
- ]
256
-
257
- # add 64 bit search paths
258
- if inspec.os.arch == 'x86_64'
259
- search_paths << 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
260
- search_paths << 'HKCU:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
261
- end
262
-
263
- # Find the package
264
- cmd = inspec.command <<-EOF.gsub(/^\s*/, '')
265
- Get-ItemProperty (@("#{search_paths.join('", "')}") | Where-Object { Test-Path $_ }) |
266
- Where-Object { $_.DisplayName -like "#{package_name}" -or $_.PSChildName -like "#{package_name}" } |
267
- Select-Object -Property DisplayName,DisplayVersion | ConvertTo-Json
268
- EOF
269
-
270
- # We cannot rely on `exit_status` since PowerShell always exits 0 from the
271
- # above command. Instead, if no package is found the output of the command
272
- # will be `''` so we can use that to return `{}` to match the behavior of
273
- # other package managers.
274
- return {} if cmd.stdout == ''
275
-
276
- begin
277
- package = JSON.parse(cmd.stdout)
278
- rescue JSON::ParserError => e
279
- raise Inspec::Exceptions::ResourceFailed,
280
- 'Failed to parse JSON from PowerShell. ' \
281
- "Error: #{e}"
282
- end
283
-
284
- # What if we match multiple packages? just pick the first one for now.
285
- package = package[0] if package.is_a?(Array)
286
-
287
- {
288
- name: package['DisplayName'],
289
- installed: true,
290
- version: package['DisplayVersion'],
291
- type: 'windows',
292
- }
293
- end
294
- end
295
-
296
- # AIX
297
- class BffPkg < PkgManagement
298
- def info(package_name)
299
- cmd = inspec.command("lslpp -cL #{package_name}")
300
- return {} if cmd.exit_status.to_i != 0
301
-
302
- bff_pkg = cmd.stdout.split("\n").last.split(':')
303
- {
304
- name: bff_pkg[1],
305
- installed: true,
306
- version: bff_pkg[2],
307
- type: 'bff',
308
- }
309
- end
310
- end
311
-
312
- # Solaris
313
- class SolarisPkg < PkgManagement
314
- def info(package_name)
315
- if inspec.os[:release].to_i <= 10
316
- solaris10_info(package_name)
317
- else
318
- solaris11_info(package_name)
319
- end
320
- end
321
-
322
- # solaris 10
323
- def solaris10_info(package_name)
324
- cmd = inspec.command("pkginfo -l #{package_name}")
325
- return {} if cmd.exit_status.to_i != 0
326
-
327
- params = SimpleConfig.new(
328
- cmd.stdout.chomp,
329
- assignment_regex: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
330
- multiple_values: false,
331
- ).params
332
-
333
- # parse 11.10.0,REV=2006.05.18.01.46
334
- v = params['VERSION'].split(',')
335
- {
336
- name: params['PKGINST'],
337
- installed: true,
338
- version: v[0] + '-' + v[1].split('=')[1],
339
- type: 'pkg',
340
- }
341
- end
342
-
343
- # solaris 11
344
- def solaris11_info(package_name)
345
- cmd = inspec.command("pkg info #{package_name}")
346
- return {} if cmd.exit_status.to_i != 0
347
-
348
- params = SimpleConfig.new(
349
- cmd.stdout.chomp,
350
- assignment_regex: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
351
- multiple_values: false,
352
- ).params
353
-
354
- {
355
- name: params['Name'],
356
- installed: true,
357
- # 0.5.11-0.175.3.1.0.5.0
358
- version: "#{params['Version']}-#{params['Branch']}",
359
- type: 'pkg',
360
- }
361
- end
362
- end
363
- end
1
+ # encoding: utf-8
2
+
3
+ # Resource to determine package information
4
+ #
5
+ # Usage:
6
+ # describe package('nginx') do
7
+ # it { should be_installed }
8
+ # end
9
+ module Inspec::Resources
10
+ class Package < Inspec.resource(1)
11
+ name 'package'
12
+ supports platform: 'unix'
13
+ supports platform: 'windows'
14
+ desc 'Use the package InSpec audit resource to test if the named package and/or package version is installed on the system.'
15
+ example "
16
+ describe package('nginx') do
17
+ it { should be_installed }
18
+ it { should_not be_held } # for dpkg platforms that support holding a version from being upgraded
19
+ its('version') { should eq 1.9.5 }
20
+ end
21
+ "
22
+
23
+ def initialize(package_name, opts = {}) # rubocop:disable Metrics/AbcSize
24
+ @package_name = package_name
25
+ @name = @package_name
26
+ @cache = nil
27
+ # select package manager
28
+ @pkgman = nil
29
+
30
+ os = inspec.os
31
+ if os.debian?
32
+ @pkgman = Deb.new(inspec)
33
+ elsif os.redhat? || %w{suse amazon fedora}.include?(os[:family])
34
+ @pkgman = Rpm.new(inspec, opts)
35
+ elsif ['arch'].include?(os[:name])
36
+ @pkgman = Pacman.new(inspec)
37
+ elsif ['darwin'].include?(os[:family])
38
+ @pkgman = Brew.new(inspec)
39
+ elsif inspec.os.windows?
40
+ @pkgman = WindowsPkg.new(inspec)
41
+ elsif ['aix'].include?(os[:family])
42
+ @pkgman = BffPkg.new(inspec)
43
+ elsif os.solaris?
44
+ @pkgman = SolarisPkg.new(inspec)
45
+ elsif ['hpux'].include?(os[:family])
46
+ @pkgman = HpuxPkg.new(inspec)
47
+ else
48
+ raise Inspec::Exceptions::ResourceSkipped, 'The `package` resource is not supported on your OS yet.'
49
+ end
50
+
51
+ evaluate_missing_requirements
52
+ end
53
+
54
+ # returns true if the package is installed
55
+ def installed?(_provider = nil, _version = nil)
56
+ info[:installed] == true
57
+ end
58
+
59
+ # returns true it the package is held (if the OS supports it)
60
+ def held?(_provider = nil, _version = nil)
61
+ info[:held] == true
62
+ end
63
+
64
+ # returns the package description
65
+ def info
66
+ return @cache if !@cache.nil?
67
+ # All `@pkgman.info` methods return `{}`. This matches that
68
+ # behavior if `@pkgman` can't be determined, thus avoiding the
69
+ # `undefined method 'info' for nil:NilClass` error
70
+ return {} if @pkgman.nil?
71
+ @pkgman.info(@package_name)
72
+ end
73
+
74
+ # return the package version
75
+ def version
76
+ info = @pkgman.info(@package_name)
77
+ info[:version]
78
+ end
79
+
80
+ def to_s
81
+ "System Package #{@package_name}"
82
+ end
83
+
84
+ private
85
+
86
+ def evaluate_missing_requirements
87
+ missing_requirements_string = @pkgman.missing_requirements.uniq.join(', ')
88
+ return if missing_requirements_string.empty?
89
+ raise Inspec::Exceptions::ResourceSkipped, "The following requirements are not met for this resource: #{missing_requirements_string}"
90
+ end
91
+ end
92
+
93
+ class PkgManagement
94
+ attr_reader :inspec
95
+ def initialize(inspec)
96
+ @inspec = inspec
97
+ end
98
+
99
+ def missing_requirements
100
+ # Each provider can provide an Array of missing requirements that will be
101
+ # combined into a `ResourceSkipped` exception message.
102
+ []
103
+ end
104
+ end
105
+
106
+ # Debian / Ubuntu
107
+ class Deb < PkgManagement
108
+ def info(package_name)
109
+ cmd = inspec.command("dpkg -s #{package_name}")
110
+ return {} if cmd.exit_status.to_i != 0
111
+
112
+ params = SimpleConfig.new(
113
+ cmd.stdout.chomp,
114
+ assignment_regex: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
115
+ multiple_values: false,
116
+ ).params
117
+ # If the package is installed, Status is "install ok installed"
118
+ # If the package is installed and marked hold, Status is "hold ok installed"
119
+ # If the package is removed and not purged, Status is "deinstall ok config-files" with exit_status 0
120
+ # If the package is purged cmd fails with non-zero exit status
121
+ {
122
+ name: params['Package'],
123
+ installed: params['Status'].split(' ')[2] == 'installed',
124
+ held: params['Status'].split(' ')[0] == 'hold',
125
+ version: params['Version'],
126
+ type: 'deb',
127
+ }
128
+ end
129
+ end
130
+
131
+ # RHEL family
132
+ class Rpm < PkgManagement
133
+ def initialize(inspec, opts)
134
+ super(inspec)
135
+
136
+ @dbpath = opts.fetch(:rpm_dbpath, nil)
137
+ end
138
+
139
+ def missing_requirements
140
+ missing_requirements = []
141
+
142
+ unless @dbpath.nil? || inspec.directory(@dbpath).directory?
143
+ missing_requirements << "RPMDB #{@dbpath} does not exist"
144
+ end
145
+
146
+ missing_requirements
147
+ end
148
+
149
+ def info(package_name)
150
+ rpm_cmd = rpm_command(package_name)
151
+ cmd = inspec.command(rpm_cmd)
152
+ # CentOS does not return an error code if the package is not installed,
153
+ # therefore we need to check for emptyness
154
+ return {} if cmd.exit_status.to_i != 0 || cmd.stdout.chomp.empty?
155
+ params = SimpleConfig.new(
156
+ cmd.stdout.chomp,
157
+ assignment_regex: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
158
+ multiple_values: false,
159
+ ).params
160
+ # On some (all?) systems, the linebreak before the vendor line is missing
161
+ if params['Version'] =~ /\s*Vendor:/
162
+ v = params['Version'].split(' ')[0]
163
+ else
164
+ v = params['Version']
165
+ end
166
+ # On some (all?) systems, the linebreak before the build line is missing
167
+ if params['Release'] =~ /\s*Build Date:/
168
+ r = params['Release'].split(' ')[0]
169
+ else
170
+ r = params['Release']
171
+ end
172
+ {
173
+ name: params['Name'],
174
+ installed: true,
175
+ version: "#{v}-#{r}",
176
+ type: 'rpm',
177
+ }
178
+ end
179
+
180
+ private
181
+
182
+ def rpm_command(package_name)
183
+ cmd = ''
184
+ cmd += 'rpm -qia'
185
+ cmd += " --dbpath #{@dbpath}" if @dbpath
186
+ cmd += ' ' + package_name
187
+
188
+ cmd
189
+ end
190
+ end
191
+
192
+ # MacOS / Darwin implementation
193
+ class Brew < PkgManagement
194
+ def info(package_name)
195
+ brew_path = inspec.command('brew').exist? ? 'brew' : '/usr/local/bin/brew'
196
+ cmd = inspec.command("#{brew_path} info --json=v1 #{package_name}")
197
+ return {} if cmd.exit_status.to_i != 0
198
+ # parse data
199
+ pkg = JSON.parse(cmd.stdout)[0]
200
+ {
201
+ name: pkg['name'],
202
+ installed: true,
203
+ version: pkg['installed'][0]['version'],
204
+ type: 'brew',
205
+ }
206
+ rescue JSON::ParserError => e
207
+ raise Inspec::Exceptions::ResourceFailed,
208
+ 'Failed to parse JSON from `brew` command. ' \
209
+ "Error: #{e}"
210
+ end
211
+ end
212
+
213
+ # Arch Linux
214
+ class Pacman < PkgManagement
215
+ def info(package_name)
216
+ cmd = inspec.command("pacman -Qi #{package_name}")
217
+ return {} if cmd.exit_status.to_i != 0
218
+
219
+ params = SimpleConfig.new(
220
+ cmd.stdout.chomp,
221
+ assignment_regex: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
222
+ multiple_values: false,
223
+ ).params
224
+
225
+ {
226
+ name: params['Name'],
227
+ installed: true,
228
+ version: params['Version'],
229
+ type: 'pacman',
230
+ }
231
+ end
232
+ end
233
+
234
+ class HpuxPkg < PkgManagement
235
+ def info(package_name)
236
+ cmd = inspec.command("swlist -l product | grep #{package_name}")
237
+ return {} if cmd.exit_status.to_i != 0
238
+ pkg = cmd.stdout.strip.split(' ')
239
+ {
240
+ name: pkg[0],
241
+ installed: true,
242
+ version: pkg[1],
243
+ type: 'pkg',
244
+ }
245
+ end
246
+ end
247
+
248
+ # Determines the installed packages on Windows using the Windows package registry entries.
249
+ # @see: http://blogs.technet.com/b/heyscriptingguy/archive/2013/11/15/use-powershell-to-find-installed-software.aspx
250
+ class WindowsPkg < PkgManagement
251
+ def info(package_name)
252
+ search_paths = [
253
+ 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
254
+ 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
255
+ ]
256
+
257
+ # add 64 bit search paths
258
+ if inspec.os.arch == 'x86_64'
259
+ search_paths << 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
260
+ search_paths << 'HKCU:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
261
+ end
262
+
263
+ # Find the package
264
+ cmd = inspec.command <<-EOF.gsub(/^\s*/, '')
265
+ Get-ItemProperty (@("#{search_paths.join('", "')}") | Where-Object { Test-Path $_ }) |
266
+ Where-Object { $_.DisplayName -like "#{package_name}" -or $_.PSChildName -like "#{package_name}" } |
267
+ Select-Object -Property DisplayName,DisplayVersion | ConvertTo-Json
268
+ EOF
269
+
270
+ # We cannot rely on `exit_status` since PowerShell always exits 0 from the
271
+ # above command. Instead, if no package is found the output of the command
272
+ # will be `''` so we can use that to return `{}` to match the behavior of
273
+ # other package managers.
274
+ return {} if cmd.stdout == ''
275
+
276
+ begin
277
+ package = JSON.parse(cmd.stdout)
278
+ rescue JSON::ParserError => e
279
+ raise Inspec::Exceptions::ResourceFailed,
280
+ 'Failed to parse JSON from PowerShell. ' \
281
+ "Error: #{e}"
282
+ end
283
+
284
+ # What if we match multiple packages? just pick the first one for now.
285
+ package = package[0] if package.is_a?(Array)
286
+
287
+ {
288
+ name: package['DisplayName'],
289
+ installed: true,
290
+ version: package['DisplayVersion'],
291
+ type: 'windows',
292
+ }
293
+ end
294
+ end
295
+
296
+ # AIX
297
+ class BffPkg < PkgManagement
298
+ def info(package_name)
299
+ cmd = inspec.command("lslpp -cL #{package_name}")
300
+ return {} if cmd.exit_status.to_i != 0
301
+
302
+ bff_pkg = cmd.stdout.split("\n").last.split(':')
303
+ {
304
+ name: bff_pkg[1],
305
+ installed: true,
306
+ version: bff_pkg[2],
307
+ type: 'bff',
308
+ }
309
+ end
310
+ end
311
+
312
+ # Solaris
313
+ class SolarisPkg < PkgManagement
314
+ def info(package_name)
315
+ if inspec.os[:release].to_i <= 10
316
+ solaris10_info(package_name)
317
+ else
318
+ solaris11_info(package_name)
319
+ end
320
+ end
321
+
322
+ # solaris 10
323
+ def solaris10_info(package_name)
324
+ cmd = inspec.command("pkginfo -l #{package_name}")
325
+ return {} if cmd.exit_status.to_i != 0
326
+
327
+ params = SimpleConfig.new(
328
+ cmd.stdout.chomp,
329
+ assignment_regex: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
330
+ multiple_values: false,
331
+ ).params
332
+
333
+ # parse 11.10.0,REV=2006.05.18.01.46
334
+ v = params['VERSION'].split(',')
335
+ {
336
+ name: params['PKGINST'],
337
+ installed: true,
338
+ version: v[0] + '-' + v[1].split('=')[1],
339
+ type: 'pkg',
340
+ }
341
+ end
342
+
343
+ # solaris 11
344
+ def solaris11_info(package_name)
345
+ cmd = inspec.command("pkg info #{package_name}")
346
+ return {} if cmd.exit_status.to_i != 0
347
+
348
+ params = SimpleConfig.new(
349
+ cmd.stdout.chomp,
350
+ assignment_regex: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
351
+ multiple_values: false,
352
+ ).params
353
+
354
+ {
355
+ name: params['Name'],
356
+ installed: true,
357
+ # 0.5.11-0.175.3.1.0.5.0
358
+ version: "#{params['Version']}-#{params['Branch']}",
359
+ type: 'pkg',
360
+ }
361
+ end
362
+ end
363
+ end