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,69 +1,69 @@
1
- class AwsVpc < Inspec.resource(1)
2
- name 'aws_vpc'
3
- desc 'Verifies settings for AWS VPC'
4
- example "
5
- describe aws_vpc do
6
- it { should be_default }
7
- its('cidr_block') { should cmp '10.0.0.0/16' }
8
- end
9
- "
10
- supports platform: 'aws'
11
-
12
- include AwsSingularResourceMixin
13
-
14
- def to_s
15
- "VPC #{vpc_id}"
16
- end
17
-
18
- [:cidr_block, :dhcp_options_id, :state, :vpc_id, :instance_tenancy, :is_default].each do |property|
19
- define_method(property) do
20
- @vpc[property]
21
- end
22
- end
23
-
24
- alias default? is_default
25
-
26
- private
27
-
28
- def validate_params(raw_params)
29
- validated_params = check_resource_param_names(
30
- raw_params: raw_params,
31
- allowed_params: [:vpc_id],
32
- allowed_scalar_name: :vpc_id,
33
- allowed_scalar_type: String,
34
- )
35
-
36
- if validated_params.key?(:vpc_id) && validated_params[:vpc_id] !~ /^vpc\-[0-9a-f]{8}/
37
- raise ArgumentError, 'aws_vpc VPC ID must be in the format "vpc-" followed by 8 hexadecimal characters.'
38
- end
39
-
40
- validated_params
41
- end
42
-
43
- def fetch_from_api
44
- backend = BackendFactory.create(inspec_runner)
45
-
46
- if @vpc_id.nil?
47
- filter = { name: 'isDefault', values: ['true'] }
48
- else
49
- filter = { name: 'vpc-id', values: [@vpc_id] }
50
- end
51
-
52
- resp = backend.describe_vpcs({ filters: [filter] })
53
-
54
- @vpc = resp.vpcs[0].to_h
55
- @vpc_id = @vpc[:vpc_id]
56
- @exists = !@vpc.empty?
57
- end
58
-
59
- class Backend
60
- class AwsClientApi < AwsBackendBase
61
- BackendFactory.set_default_backend(self)
62
- self.aws_client_class = Aws::EC2::Client
63
-
64
- def describe_vpcs(query)
65
- aws_service_client.describe_vpcs(query)
66
- end
67
- end
68
- end
69
- end
1
+ class AwsVpc < Inspec.resource(1)
2
+ name 'aws_vpc'
3
+ desc 'Verifies settings for AWS VPC'
4
+ example "
5
+ describe aws_vpc do
6
+ it { should be_default }
7
+ its('cidr_block') { should cmp '10.0.0.0/16' }
8
+ end
9
+ "
10
+ supports platform: 'aws'
11
+
12
+ include AwsSingularResourceMixin
13
+
14
+ def to_s
15
+ "VPC #{vpc_id}"
16
+ end
17
+
18
+ [:cidr_block, :dhcp_options_id, :state, :vpc_id, :instance_tenancy, :is_default].each do |property|
19
+ define_method(property) do
20
+ @vpc[property]
21
+ end
22
+ end
23
+
24
+ alias default? is_default
25
+
26
+ private
27
+
28
+ def validate_params(raw_params)
29
+ validated_params = check_resource_param_names(
30
+ raw_params: raw_params,
31
+ allowed_params: [:vpc_id],
32
+ allowed_scalar_name: :vpc_id,
33
+ allowed_scalar_type: String,
34
+ )
35
+
36
+ if validated_params.key?(:vpc_id) && validated_params[:vpc_id] !~ /^vpc\-[0-9a-f]{8}/
37
+ raise ArgumentError, 'aws_vpc VPC ID must be in the format "vpc-" followed by 8 hexadecimal characters.'
38
+ end
39
+
40
+ validated_params
41
+ end
42
+
43
+ def fetch_from_api
44
+ backend = BackendFactory.create(inspec_runner)
45
+
46
+ if @vpc_id.nil?
47
+ filter = { name: 'isDefault', values: ['true'] }
48
+ else
49
+ filter = { name: 'vpc-id', values: [@vpc_id] }
50
+ end
51
+
52
+ resp = backend.describe_vpcs({ filters: [filter] })
53
+
54
+ @vpc = resp.vpcs[0].to_h
55
+ @vpc_id = @vpc[:vpc_id]
56
+ @exists = !@vpc.empty?
57
+ end
58
+
59
+ class Backend
60
+ class AwsClientApi < AwsBackendBase
61
+ BackendFactory.set_default_backend(self)
62
+ self.aws_client_class = Aws::EC2::Client
63
+
64
+ def describe_vpcs(query)
65
+ aws_service_client.describe_vpcs(query)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -1,45 +1,45 @@
1
- class AwsVpcs < Inspec.resource(1)
2
- name 'aws_vpcs'
3
- desc 'Verifies settings for AWS VPCs in bulk'
4
- example '
5
- describe aws_vpcs do
6
- it { should exist }
7
- end
8
- '
9
- supports platform: 'aws'
10
-
11
- include AwsPluralResourceMixin
12
-
13
- # Underlying FilterTable implementation.
14
- filter = FilterTable.create
15
- filter.add_accessor(:entries)
16
- .add(:exists?) { |x| !x.entries.empty? }
17
- filter.connect(self, :table)
18
-
19
- def validate_params(raw_params)
20
- # No params yet
21
- unless raw_params.empty?
22
- raise ArgumentError, 'aws_vpcs does not accept resource parameters'
23
- end
24
- raw_params
25
- end
26
-
27
- def to_s
28
- 'VPCs'
29
- end
30
-
31
- def fetch_from_api
32
- @table = BackendFactory.create(inspec_runner).describe_vpcs.to_h[:vpcs]
33
- end
34
-
35
- class Backend
36
- class AwsClientApi < AwsBackendBase
37
- BackendFactory.set_default_backend(self)
38
- self.aws_client_class = Aws::EC2::Client
39
-
40
- def describe_vpcs(query = {})
41
- aws_service_client.describe_vpcs(query)
42
- end
43
- end
44
- end
45
- end
1
+ class AwsVpcs < Inspec.resource(1)
2
+ name 'aws_vpcs'
3
+ desc 'Verifies settings for AWS VPCs in bulk'
4
+ example '
5
+ describe aws_vpcs do
6
+ it { should exist }
7
+ end
8
+ '
9
+ supports platform: 'aws'
10
+
11
+ include AwsPluralResourceMixin
12
+
13
+ # Underlying FilterTable implementation.
14
+ filter = FilterTable.create
15
+ filter.add_accessor(:entries)
16
+ .add(:exists?) { |x| !x.entries.empty? }
17
+ filter.connect(self, :table)
18
+
19
+ def validate_params(raw_params)
20
+ # No params yet
21
+ unless raw_params.empty?
22
+ raise ArgumentError, 'aws_vpcs does not accept resource parameters'
23
+ end
24
+ raw_params
25
+ end
26
+
27
+ def to_s
28
+ 'VPCs'
29
+ end
30
+
31
+ def fetch_from_api
32
+ @table = BackendFactory.create(inspec_runner).describe_vpcs.to_h[:vpcs]
33
+ end
34
+
35
+ class Backend
36
+ class AwsClientApi < AwsBackendBase
37
+ BackendFactory.set_default_backend(self)
38
+ self.aws_client_class = Aws::EC2::Client
39
+
40
+ def describe_vpcs(query = {})
41
+ aws_service_client.describe_vpcs(query)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,377 +1,377 @@
1
- # Base class for Azure Resources. This allows the generic class to work
2
- # as well as the specific target resources for Azure Resources
3
- #
4
- # @author Russell Seymour
5
- module Inspec::Resources
6
- class AzureResourceBase < Inspec.resource(1)
7
- attr_reader :opts, :client, :azure
8
-
9
- # Constructor that retreives the specified resource
10
- #
11
- # The opts hash should contain the following
12
- # :group_name - name of the resource group in which to look for items
13
- # :type - the type of Azure resource to look for
14
- # :apiversion - API version to use when looking for a specific resource
15
- # :name - name of the resource to find
16
- #
17
- # @author Russell Seymour
18
- #
19
- # @param [Hash] opts Hashtable of options as highlighted above
20
- # rubocop:disable Metrics/AbcSize
21
- def initialize(opts)
22
- # declare the hashtable of counts
23
- @counts = {}
24
- @total = 0
25
- @opts = opts
26
-
27
- # Determine if the environment variables for the options have been set
28
- option_var_names = {
29
- group_name: 'AZURE_RESOURCE_GROUP_NAME',
30
- name: 'AZURE_RESOURCE_NAME',
31
- type: 'AZURE_RESOURCE_TYPE',
32
- apiversion: 'AZURE_RESOURCE_API_VERSION',
33
- }
34
- option_var_names.each do |option_name, env_var_name|
35
- opts[option_name] = ENV[env_var_name] unless ENV[env_var_name].nil?
36
- end
37
-
38
- @azure = inspec.backend
39
- @client = azure.azure_client
40
- @failed_resource = false
41
- end
42
-
43
- def failed_resource?
44
- @failed_resource
45
- end
46
-
47
- def catch_azure_errors
48
- yield
49
- rescue MsRestAzure::AzureOperationError => e
50
- # e.message is actually a massive stringified JSON, which might be useful in the future.
51
- # You want error_message here.
52
- fail_resource e.error_message
53
- @failed_resource = true
54
- nil
55
- end
56
-
57
- # Return information about the resource group
58
- def resource_group
59
- catch_azure_errors do
60
- resource_group = client.resource_groups.get(opts[:group_name])
61
-
62
- # create the methods for the resource group object
63
- dm = AzureResourceDynamicMethods.new
64
- dm.create_methods(self, resource_group)
65
- end
66
- end
67
-
68
- def resources
69
- resources = nil
70
- catch_azure_errors do
71
- resources = client.resources.list_by_resource_group(opts[:group_name])
72
- end
73
- return if failed_resource?
74
-
75
- # filter the resources based on the type, and the name if they been specified
76
- resources = filter_resources(resources, opts)
77
-
78
- # if there is one resource then define methods on this class
79
- if resources.count == 1
80
- @total = 1
81
-
82
- resource = nil
83
- catch_azure_errors do
84
- # get the apiversion for the resource, if one has not been specified
85
- apiversion = azure.get_api_version(resources[0].type, opts)
86
-
87
- # get the resource by id so it can be interrogated
88
- resource = client.resources.get_by_id(resources[0].id, apiversion)
89
- end
90
- return if failed_resource?
91
-
92
- dm = AzureResourceDynamicMethods.new
93
-
94
- dm.create_methods(self, resource)
95
- else
96
-
97
- # As there are many resources, parse each one so that it can be
98
- # interrogated by the FilterTable
99
- # @probes = parse_resources(resources, azure)
100
- @probes = resources.each.map do |item|
101
- # update the total
102
- @total += 1
103
-
104
- # determine the counts for each type
105
- namespace, type_name = item.type.split(/\./)
106
- counts.key?(namespace) ? false : counts[namespace] = {}
107
- counts[namespace].key?(type_name) ? counts[namespace][type_name] += 1 : counts[namespace][type_name] = 1
108
-
109
- # get the detail about the resource
110
- apiversion = azure.get_api_version(item.type, opts)
111
- resource = client.resources.get_by_id(item.id, apiversion)
112
-
113
- # parse the resource
114
- parse_resource(resource)
115
- end.compact
116
-
117
- # Iterate around the counts and create the necessary classes
118
- counts.each do |namespace, ns_counts|
119
- define_singleton_method namespace do
120
- AzureResourceTypeCounts.new(ns_counts)
121
- end
122
- end
123
- end
124
- end
125
-
126
- # Does the resource have any tags?
127
- #
128
- # If it is a Hashtable then it does not, because there was nothing to parse so there is not
129
- # a nested object to work with
130
- #
131
- # @author Russell Seymour
132
- def has_tags?
133
- tags.is_a?(Hash) ? false : true
134
- end
135
-
136
- # Returns how many tags have been set on the resource
137
- #
138
- # @author Russell Seymour
139
- def tag_count
140
- tags.count
141
- end
142
-
143
- # It is necessary to be able to test the tags of a resource. It is possible to say of the
144
- # resource has tags or not, and it is possible to check that the tags include a specific tag
145
- # However the value is not accessible, this function creates methods for all the tags that
146
- # are available.
147
- #
148
- # The format of the method name is '<TAG_NAME>_tag' and will return the value of that tag
149
- #
150
- # Disabling rubopcop check. If this is set as a normal if..then..end statement there is a
151
- # violation stating it should use a guard. When using a guard it throws this error
152
- #
153
- # @author Russell Seymour
154
- def create_tag_methods
155
- # Iterate around the items of the tags and create the necessary access methods
156
- tags.item.each do |name, value|
157
- method_name = format('%s_tag', name)
158
- define_singleton_method method_name do
159
- value
160
- end
161
- end if defined?(tags.item)
162
- end
163
-
164
- private
165
-
166
- # Filter the resources that are returned by the options that have been specified
167
- #
168
- def filter_resources(resources, opts)
169
- if opts[:type] && opts[:name]
170
- resources.select { |r| r.type == opts[:type] && r.name == opts[:name] }
171
- elsif opts[:type]
172
- resources.select { |r| r.type == opts[:type] }
173
- elsif opts[:name]
174
- resources.select { |r| r.name == opts[:name] }
175
- else
176
- resources
177
- end
178
- end
179
- end
180
- end
181
-
182
- # Class to create methods on the calling object at run time.
183
- # Each of the Azure Resources have different attributes and properties, and they all need
184
- # to be testable. To do this no methods are hardcoded, each on is craeted based on the
185
- # information returned from Azure.
186
- #
187
- # The class is a helper class essentially as it creates the methods on the calling class
188
- # rather than itself. This means that there is less duplication of code and it can be
189
- # reused easily.
190
- #
191
- # @author Russell Seymour
192
- # @since 0.2.0
193
- class AzureResourceDynamicMethods
194
- # Given the calling object and its data, create the methods on the object according
195
- # to the data that has been retrieved. Various types of data can be returned so the method
196
- # checks the type to ensure that the necessary methods are configured correctly
197
- #
198
- # @param AzureResourceProbe|AzureResource object The object on which the methods should be craeted
199
- # @param variant data The data from which the methods should be created
200
- def create_methods(object, data)
201
- # Check the type of data as this affects the setup of the methods
202
- # If it is an Azure Generic Resource then setup methods for each of
203
- # the instance variables
204
- case data.class.to_s
205
- when /^Azure::Resources::Mgmt::.*::Models::GenericResource$/,
206
- /^Azure::Resources::Mgmt::.*::Models::ResourceGroup$/
207
- # iterate around the instance variables
208
- data.instance_variables.each do |var|
209
- create_method(object, var.to_s.delete('@'), data.instance_variable_get(var))
210
- end
211
- # When the data is a Hash object iterate around each of the key value pairs and
212
- # craete a method for each one.
213
- when 'Hash'
214
- data.each do |key, value|
215
- create_method(object, key, value)
216
- end
217
- end
218
- end
219
-
220
- private
221
-
222
- # Method that is responsible for creating the method on the calling object. This is
223
- # because some nesting maybe required. For example of the value is a Hash then it will
224
- # need to have an AzureResourceProbe create for each key, whereas if it is a simple
225
- # string then the value just needs to be returned
226
- #
227
- # @private
228
- #
229
- # @param AzureResourceProbe|AzureResource object Object on which the methods need to be created
230
- # @param string name The name of the method
231
- # @param variant value The value that needs to be returned by the method
232
- def create_method(object, name, value)
233
- # Create the necessary method based on the var that has been passed
234
- # Test the value for its type so that the method can be setup correctly
235
- case value.class.to_s
236
- when 'String', 'Integer', 'TrueClass', 'FalseClass', 'Fixnum'
237
- object.define_singleton_method name do
238
- value
239
- end
240
- when 'Hash'
241
- value.count.zero? ? return_value = value : return_value = AzureResourceProbe.new(value)
242
- object.define_singleton_method name do
243
- return_value
244
- end
245
- when /^Azure::Resources::Mgmt::.*::Models::ResourceGroupProperties$/
246
- # This is a special case where the properties of the resource group is not a simple JSON model
247
- # This is because the plugin is using the Azure SDK to get this information so it is an SDK object
248
- # that has to be interrogated in a different way. This is the only object type that behaves like this
249
- value.instance_variables.each do |var|
250
- create_method(object, var.to_s.delete('@'), value.instance_variable_get(var))
251
- end
252
- when 'Array'
253
- # Some things are just string or integer arrays
254
- # Check this by seeing if the first element is a string / integer / boolean or
255
- # a hashtable
256
- # This may not be the best methid, but short of testing all elements in the array, this is
257
- # the quickest test
258
- case value[0].class.to_s
259
- when 'String', 'Integer', 'TrueClass', 'FalseClass', 'Fixnum'
260
- probes = value
261
- else
262
- probes = []
263
- value.each do |value_item|
264
- probes << AzureResourceProbe.new(value_item)
265
- end
266
- end
267
- object.define_singleton_method name do
268
- probes
269
- end
270
- end
271
- end
272
- end
273
-
274
- # Class object to maintain a count of the Azure Resource types that are found
275
- # when a less specific test is carried out. For example if all the resoures of a resource
276
- # group are called for, there will be variaous types and number of those types.
277
- #
278
- # Each type is namespaced, so for example a virtual machine has the type 'Microsoft.Compute/virtualMachines'
279
- # This is broken down into the 'Microsoft' class with the type 'Compute/virtualMachines'
280
- # This has been done for two reasons:
281
- # 1. Enable the dotted notation to work in the test
282
- # 2. Allow third party resource types ot be catered for if they are ever enabled by Microsoft
283
- #
284
- # @author Russell Seymour
285
- # @since 0.2.0
286
- class AzureResourceTypeCounts
287
- # Constructor to setup a new class for a specific Azure Resource type.
288
- # It should be passed a hashtable with information such as:
289
- # {
290
- # "Compute/virtualMachines" => 2,
291
- # "Network/networkInterfaces" => 3
292
- # }
293
- # This will result in two methods being created on the class:
294
- # - Compute/virtualNetworks
295
- # - Network/networkInterfaces
296
- # Each of which will return the corresponding count value
297
- #
298
- # @param Hash counts Hash table of types and the count of each one
299
- #
300
- # @return AzureResourceTypeCounts
301
- def initialize(counts)
302
- counts.each do |type, count|
303
- define_singleton_method type do
304
- count
305
- end
306
- end
307
- end
308
- end
309
-
310
- # Class object that is created for each element that is returned by Azure.
311
- # This is what is interogated by Inspec. If they are nested hashes, then this results
312
- # in nested AzureResourceProbe objects.
313
- #
314
- # For example, if the following was seen in an Azure Resource
315
- # properties -> storageProfile -> imageReference
316
- # Would result in the following nestec classes
317
- # AzureResource -> AzureResourceProbe -> AzureResourceProbe
318
- #
319
- # The methods for each of the classes are dynamically defined at run time and will
320
- # match the items that are retrieved from Azure. See the 'test/integration/verify/controls' for
321
- # examples
322
- #
323
- # This class will not be called externally
324
- #
325
- # @author Russell Seymour
326
- # @since 0.2.0
327
- # @attr_reader string name Name of the Azure resource
328
- # @attr_reader string type Type of the Azure Resource
329
- # @attr_reader string location Location in Azure of the resource
330
- class AzureResourceProbe
331
- attr_reader :name, :type, :location, :item, :count
332
-
333
- # Initialize method for the class. Accepts an item, be it a scalar value, hash or Azure object
334
- # It will then create the necessary dynamic methods so that they can be called in the tests
335
- # This is accomplished by call the AzureResourceDynamicMethods
336
- #
337
- # @param varaint The item from which the class will be initialized
338
- #
339
- # @return AzureResourceProbe
340
- def initialize(item)
341
- dm = AzureResourceDynamicMethods.new
342
- dm.create_methods(self, item)
343
-
344
- # Set the item as a property on the class
345
- # This is so that it is possible to interrogate what has been added to the class and isolate them from
346
- # the standard methods that a Ruby class has.
347
- # This used for checking Tags on a resource for example
348
- # It also allows direct access if so required
349
- @item = item
350
-
351
- # Set how many items have been set
352
- @count = item.length
353
- end
354
-
355
- # Allows resources to respond to the include test
356
- # This means that things like tags can be checked for and then their value tested
357
- #
358
- # @author Russell Seymour
359
- #
360
- # @param [String] key Name of the item to look for in the @item property
361
- def include?(key)
362
- @item.key?(key)
363
- end
364
-
365
- # Give a sting like `computer_name` return the camelCase version, e.g.
366
- # computerName
367
- #
368
- # @param string data Data that needs to be converted from snake_case to camelCase
369
- #
370
- # @return string
371
- def camel_case(data)
372
- camel_case_data = data.split('_').inject([]) { |buffer, e| buffer.push(buffer.empty? ? e : e.capitalize) }.join
373
-
374
- # Ensure that gb (as in gigabytes) is uppercased
375
- camel_case_data.gsub(/[gb]/, &:upcase)
376
- end
377
- end
1
+ # Base class for Azure Resources. This allows the generic class to work
2
+ # as well as the specific target resources for Azure Resources
3
+ #
4
+ # @author Russell Seymour
5
+ module Inspec::Resources
6
+ class AzureResourceBase < Inspec.resource(1)
7
+ attr_reader :opts, :client, :azure
8
+
9
+ # Constructor that retreives the specified resource
10
+ #
11
+ # The opts hash should contain the following
12
+ # :group_name - name of the resource group in which to look for items
13
+ # :type - the type of Azure resource to look for
14
+ # :apiversion - API version to use when looking for a specific resource
15
+ # :name - name of the resource to find
16
+ #
17
+ # @author Russell Seymour
18
+ #
19
+ # @param [Hash] opts Hashtable of options as highlighted above
20
+ # rubocop:disable Metrics/AbcSize
21
+ def initialize(opts)
22
+ # declare the hashtable of counts
23
+ @counts = {}
24
+ @total = 0
25
+ @opts = opts
26
+
27
+ # Determine if the environment variables for the options have been set
28
+ option_var_names = {
29
+ group_name: 'AZURE_RESOURCE_GROUP_NAME',
30
+ name: 'AZURE_RESOURCE_NAME',
31
+ type: 'AZURE_RESOURCE_TYPE',
32
+ apiversion: 'AZURE_RESOURCE_API_VERSION',
33
+ }
34
+ option_var_names.each do |option_name, env_var_name|
35
+ opts[option_name] = ENV[env_var_name] unless ENV[env_var_name].nil?
36
+ end
37
+
38
+ @azure = inspec.backend
39
+ @client = azure.azure_client
40
+ @failed_resource = false
41
+ end
42
+
43
+ def failed_resource?
44
+ @failed_resource
45
+ end
46
+
47
+ def catch_azure_errors
48
+ yield
49
+ rescue MsRestAzure::AzureOperationError => e
50
+ # e.message is actually a massive stringified JSON, which might be useful in the future.
51
+ # You want error_message here.
52
+ fail_resource e.error_message
53
+ @failed_resource = true
54
+ nil
55
+ end
56
+
57
+ # Return information about the resource group
58
+ def resource_group
59
+ catch_azure_errors do
60
+ resource_group = client.resource_groups.get(opts[:group_name])
61
+
62
+ # create the methods for the resource group object
63
+ dm = AzureResourceDynamicMethods.new
64
+ dm.create_methods(self, resource_group)
65
+ end
66
+ end
67
+
68
+ def resources
69
+ resources = nil
70
+ catch_azure_errors do
71
+ resources = client.resources.list_by_resource_group(opts[:group_name])
72
+ end
73
+ return if failed_resource?
74
+
75
+ # filter the resources based on the type, and the name if they been specified
76
+ resources = filter_resources(resources, opts)
77
+
78
+ # if there is one resource then define methods on this class
79
+ if resources.count == 1
80
+ @total = 1
81
+
82
+ resource = nil
83
+ catch_azure_errors do
84
+ # get the apiversion for the resource, if one has not been specified
85
+ apiversion = azure.get_api_version(resources[0].type, opts)
86
+
87
+ # get the resource by id so it can be interrogated
88
+ resource = client.resources.get_by_id(resources[0].id, apiversion)
89
+ end
90
+ return if failed_resource?
91
+
92
+ dm = AzureResourceDynamicMethods.new
93
+
94
+ dm.create_methods(self, resource)
95
+ else
96
+
97
+ # As there are many resources, parse each one so that it can be
98
+ # interrogated by the FilterTable
99
+ # @probes = parse_resources(resources, azure)
100
+ @probes = resources.each.map do |item|
101
+ # update the total
102
+ @total += 1
103
+
104
+ # determine the counts for each type
105
+ namespace, type_name = item.type.split(/\./)
106
+ counts.key?(namespace) ? false : counts[namespace] = {}
107
+ counts[namespace].key?(type_name) ? counts[namespace][type_name] += 1 : counts[namespace][type_name] = 1
108
+
109
+ # get the detail about the resource
110
+ apiversion = azure.get_api_version(item.type, opts)
111
+ resource = client.resources.get_by_id(item.id, apiversion)
112
+
113
+ # parse the resource
114
+ parse_resource(resource)
115
+ end.compact
116
+
117
+ # Iterate around the counts and create the necessary classes
118
+ counts.each do |namespace, ns_counts|
119
+ define_singleton_method namespace do
120
+ AzureResourceTypeCounts.new(ns_counts)
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ # Does the resource have any tags?
127
+ #
128
+ # If it is a Hashtable then it does not, because there was nothing to parse so there is not
129
+ # a nested object to work with
130
+ #
131
+ # @author Russell Seymour
132
+ def has_tags?
133
+ tags.is_a?(Hash) ? false : true
134
+ end
135
+
136
+ # Returns how many tags have been set on the resource
137
+ #
138
+ # @author Russell Seymour
139
+ def tag_count
140
+ tags.count
141
+ end
142
+
143
+ # It is necessary to be able to test the tags of a resource. It is possible to say of the
144
+ # resource has tags or not, and it is possible to check that the tags include a specific tag
145
+ # However the value is not accessible, this function creates methods for all the tags that
146
+ # are available.
147
+ #
148
+ # The format of the method name is '<TAG_NAME>_tag' and will return the value of that tag
149
+ #
150
+ # Disabling rubopcop check. If this is set as a normal if..then..end statement there is a
151
+ # violation stating it should use a guard. When using a guard it throws this error
152
+ #
153
+ # @author Russell Seymour
154
+ def create_tag_methods
155
+ # Iterate around the items of the tags and create the necessary access methods
156
+ tags.item.each do |name, value|
157
+ method_name = format('%s_tag', name)
158
+ define_singleton_method method_name do
159
+ value
160
+ end
161
+ end if defined?(tags.item)
162
+ end
163
+
164
+ private
165
+
166
+ # Filter the resources that are returned by the options that have been specified
167
+ #
168
+ def filter_resources(resources, opts)
169
+ if opts[:type] && opts[:name]
170
+ resources.select { |r| r.type == opts[:type] && r.name == opts[:name] }
171
+ elsif opts[:type]
172
+ resources.select { |r| r.type == opts[:type] }
173
+ elsif opts[:name]
174
+ resources.select { |r| r.name == opts[:name] }
175
+ else
176
+ resources
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+ # Class to create methods on the calling object at run time.
183
+ # Each of the Azure Resources have different attributes and properties, and they all need
184
+ # to be testable. To do this no methods are hardcoded, each on is craeted based on the
185
+ # information returned from Azure.
186
+ #
187
+ # The class is a helper class essentially as it creates the methods on the calling class
188
+ # rather than itself. This means that there is less duplication of code and it can be
189
+ # reused easily.
190
+ #
191
+ # @author Russell Seymour
192
+ # @since 0.2.0
193
+ class AzureResourceDynamicMethods
194
+ # Given the calling object and its data, create the methods on the object according
195
+ # to the data that has been retrieved. Various types of data can be returned so the method
196
+ # checks the type to ensure that the necessary methods are configured correctly
197
+ #
198
+ # @param AzureResourceProbe|AzureResource object The object on which the methods should be craeted
199
+ # @param variant data The data from which the methods should be created
200
+ def create_methods(object, data)
201
+ # Check the type of data as this affects the setup of the methods
202
+ # If it is an Azure Generic Resource then setup methods for each of
203
+ # the instance variables
204
+ case data.class.to_s
205
+ when /^Azure::Resources::Mgmt::.*::Models::GenericResource$/,
206
+ /^Azure::Resources::Mgmt::.*::Models::ResourceGroup$/
207
+ # iterate around the instance variables
208
+ data.instance_variables.each do |var|
209
+ create_method(object, var.to_s.delete('@'), data.instance_variable_get(var))
210
+ end
211
+ # When the data is a Hash object iterate around each of the key value pairs and
212
+ # craete a method for each one.
213
+ when 'Hash'
214
+ data.each do |key, value|
215
+ create_method(object, key, value)
216
+ end
217
+ end
218
+ end
219
+
220
+ private
221
+
222
+ # Method that is responsible for creating the method on the calling object. This is
223
+ # because some nesting maybe required. For example of the value is a Hash then it will
224
+ # need to have an AzureResourceProbe create for each key, whereas if it is a simple
225
+ # string then the value just needs to be returned
226
+ #
227
+ # @private
228
+ #
229
+ # @param AzureResourceProbe|AzureResource object Object on which the methods need to be created
230
+ # @param string name The name of the method
231
+ # @param variant value The value that needs to be returned by the method
232
+ def create_method(object, name, value)
233
+ # Create the necessary method based on the var that has been passed
234
+ # Test the value for its type so that the method can be setup correctly
235
+ case value.class.to_s
236
+ when 'String', 'Integer', 'TrueClass', 'FalseClass', 'Fixnum'
237
+ object.define_singleton_method name do
238
+ value
239
+ end
240
+ when 'Hash'
241
+ value.count.zero? ? return_value = value : return_value = AzureResourceProbe.new(value)
242
+ object.define_singleton_method name do
243
+ return_value
244
+ end
245
+ when /^Azure::Resources::Mgmt::.*::Models::ResourceGroupProperties$/
246
+ # This is a special case where the properties of the resource group is not a simple JSON model
247
+ # This is because the plugin is using the Azure SDK to get this information so it is an SDK object
248
+ # that has to be interrogated in a different way. This is the only object type that behaves like this
249
+ value.instance_variables.each do |var|
250
+ create_method(object, var.to_s.delete('@'), value.instance_variable_get(var))
251
+ end
252
+ when 'Array'
253
+ # Some things are just string or integer arrays
254
+ # Check this by seeing if the first element is a string / integer / boolean or
255
+ # a hashtable
256
+ # This may not be the best methid, but short of testing all elements in the array, this is
257
+ # the quickest test
258
+ case value[0].class.to_s
259
+ when 'String', 'Integer', 'TrueClass', 'FalseClass', 'Fixnum'
260
+ probes = value
261
+ else
262
+ probes = []
263
+ value.each do |value_item|
264
+ probes << AzureResourceProbe.new(value_item)
265
+ end
266
+ end
267
+ object.define_singleton_method name do
268
+ probes
269
+ end
270
+ end
271
+ end
272
+ end
273
+
274
+ # Class object to maintain a count of the Azure Resource types that are found
275
+ # when a less specific test is carried out. For example if all the resoures of a resource
276
+ # group are called for, there will be variaous types and number of those types.
277
+ #
278
+ # Each type is namespaced, so for example a virtual machine has the type 'Microsoft.Compute/virtualMachines'
279
+ # This is broken down into the 'Microsoft' class with the type 'Compute/virtualMachines'
280
+ # This has been done for two reasons:
281
+ # 1. Enable the dotted notation to work in the test
282
+ # 2. Allow third party resource types ot be catered for if they are ever enabled by Microsoft
283
+ #
284
+ # @author Russell Seymour
285
+ # @since 0.2.0
286
+ class AzureResourceTypeCounts
287
+ # Constructor to setup a new class for a specific Azure Resource type.
288
+ # It should be passed a hashtable with information such as:
289
+ # {
290
+ # "Compute/virtualMachines" => 2,
291
+ # "Network/networkInterfaces" => 3
292
+ # }
293
+ # This will result in two methods being created on the class:
294
+ # - Compute/virtualNetworks
295
+ # - Network/networkInterfaces
296
+ # Each of which will return the corresponding count value
297
+ #
298
+ # @param Hash counts Hash table of types and the count of each one
299
+ #
300
+ # @return AzureResourceTypeCounts
301
+ def initialize(counts)
302
+ counts.each do |type, count|
303
+ define_singleton_method type do
304
+ count
305
+ end
306
+ end
307
+ end
308
+ end
309
+
310
+ # Class object that is created for each element that is returned by Azure.
311
+ # This is what is interogated by Inspec. If they are nested hashes, then this results
312
+ # in nested AzureResourceProbe objects.
313
+ #
314
+ # For example, if the following was seen in an Azure Resource
315
+ # properties -> storageProfile -> imageReference
316
+ # Would result in the following nestec classes
317
+ # AzureResource -> AzureResourceProbe -> AzureResourceProbe
318
+ #
319
+ # The methods for each of the classes are dynamically defined at run time and will
320
+ # match the items that are retrieved from Azure. See the 'test/integration/verify/controls' for
321
+ # examples
322
+ #
323
+ # This class will not be called externally
324
+ #
325
+ # @author Russell Seymour
326
+ # @since 0.2.0
327
+ # @attr_reader string name Name of the Azure resource
328
+ # @attr_reader string type Type of the Azure Resource
329
+ # @attr_reader string location Location in Azure of the resource
330
+ class AzureResourceProbe
331
+ attr_reader :name, :type, :location, :item, :count
332
+
333
+ # Initialize method for the class. Accepts an item, be it a scalar value, hash or Azure object
334
+ # It will then create the necessary dynamic methods so that they can be called in the tests
335
+ # This is accomplished by call the AzureResourceDynamicMethods
336
+ #
337
+ # @param varaint The item from which the class will be initialized
338
+ #
339
+ # @return AzureResourceProbe
340
+ def initialize(item)
341
+ dm = AzureResourceDynamicMethods.new
342
+ dm.create_methods(self, item)
343
+
344
+ # Set the item as a property on the class
345
+ # This is so that it is possible to interrogate what has been added to the class and isolate them from
346
+ # the standard methods that a Ruby class has.
347
+ # This used for checking Tags on a resource for example
348
+ # It also allows direct access if so required
349
+ @item = item
350
+
351
+ # Set how many items have been set
352
+ @count = item.length
353
+ end
354
+
355
+ # Allows resources to respond to the include test
356
+ # This means that things like tags can be checked for and then their value tested
357
+ #
358
+ # @author Russell Seymour
359
+ #
360
+ # @param [String] key Name of the item to look for in the @item property
361
+ def include?(key)
362
+ @item.key?(key)
363
+ end
364
+
365
+ # Give a sting like `computer_name` return the camelCase version, e.g.
366
+ # computerName
367
+ #
368
+ # @param string data Data that needs to be converted from snake_case to camelCase
369
+ #
370
+ # @return string
371
+ def camel_case(data)
372
+ camel_case_data = data.split('_').inject([]) { |buffer, e| buffer.push(buffer.empty? ? e : e.capitalize) }.join
373
+
374
+ # Ensure that gb (as in gigabytes) is uppercased
375
+ camel_case_data.gsub(/[gb]/, &:upcase)
376
+ end
377
+ end