inspec 2.1.81 → 2.1.83

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 (507) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +101 -101
  3. data/CHANGELOG.md +3183 -3177
  4. data/Gemfile +56 -56
  5. data/LICENSE +14 -14
  6. data/MAINTAINERS.md +33 -33
  7. data/MAINTAINERS.toml +52 -52
  8. data/README.md +453 -453
  9. data/Rakefile +349 -349
  10. data/bin/inspec +12 -12
  11. data/docs/.gitignore +2 -2
  12. data/docs/README.md +41 -40
  13. data/docs/dev/control-eval.md +61 -61
  14. data/docs/dsl_inspec.md +258 -258
  15. data/docs/dsl_resource.md +100 -100
  16. data/docs/glossary.md +99 -99
  17. data/docs/habitat.md +191 -191
  18. data/docs/inspec_and_friends.md +114 -114
  19. data/docs/matchers.md +169 -169
  20. data/docs/migration.md +293 -293
  21. data/docs/platforms.md +118 -118
  22. data/docs/plugin_kitchen_inspec.md +50 -50
  23. data/docs/profiles.md +378 -378
  24. data/docs/reporters.md +105 -105
  25. data/docs/resources/aide_conf.md.erb +75 -75
  26. data/docs/resources/apache.md.erb +67 -67
  27. data/docs/resources/apache_conf.md.erb +68 -68
  28. data/docs/resources/apt.md.erb +71 -71
  29. data/docs/resources/audit_policy.md.erb +47 -47
  30. data/docs/resources/auditd.md.erb +79 -79
  31. data/docs/resources/auditd_conf.md.erb +68 -68
  32. data/docs/resources/aws_cloudtrail_trail.md.erb +155 -155
  33. data/docs/resources/aws_cloudtrail_trails.md.erb +86 -86
  34. data/docs/resources/aws_cloudwatch_alarm.md.erb +91 -91
  35. data/docs/resources/aws_cloudwatch_log_metric_filter.md.erb +154 -154
  36. data/docs/resources/aws_config_delivery_channel.md.erb +101 -101
  37. data/docs/resources/aws_config_recorder.md.erb +86 -86
  38. data/docs/resources/aws_ec2_instance.md.erb +112 -112
  39. data/docs/resources/aws_ec2_instances.md.erb +79 -79
  40. data/docs/resources/aws_iam_access_key.md.erb +129 -129
  41. data/docs/resources/aws_iam_access_keys.md.erb +204 -204
  42. data/docs/resources/aws_iam_group.md.erb +64 -64
  43. data/docs/resources/aws_iam_groups.md.erb +49 -49
  44. data/docs/resources/aws_iam_password_policy.md.erb +82 -82
  45. data/docs/resources/aws_iam_policies.md.erb +87 -87
  46. data/docs/resources/aws_iam_policy.md.erb +245 -245
  47. data/docs/resources/aws_iam_role.md.erb +69 -69
  48. data/docs/resources/aws_iam_root_user.md.erb +76 -76
  49. data/docs/resources/aws_iam_user.md.erb +120 -120
  50. data/docs/resources/aws_iam_users.md.erb +279 -279
  51. data/docs/resources/aws_kms_key.md.erb +177 -177
  52. data/docs/resources/aws_kms_keys.md.erb +89 -89
  53. data/docs/resources/aws_rds_instance.md.erb +66 -66
  54. data/docs/resources/aws_route_table.md.erb +53 -53
  55. data/docs/resources/aws_route_tables.md.erb +55 -55
  56. data/docs/resources/aws_s3_bucket.md.erb +146 -146
  57. data/docs/resources/aws_s3_bucket_object.md.erb +89 -89
  58. data/docs/resources/aws_s3_buckets.md.erb +59 -59
  59. data/docs/resources/aws_security_group.md.erb +296 -296
  60. data/docs/resources/aws_security_groups.md.erb +97 -97
  61. data/docs/resources/aws_sns_subscription.md.erb +130 -130
  62. data/docs/resources/aws_sns_topic.md.erb +69 -69
  63. data/docs/resources/aws_sns_topics.md.erb +58 -58
  64. data/docs/resources/aws_subnet.md.erb +140 -140
  65. data/docs/resources/aws_subnets.md.erb +132 -132
  66. data/docs/resources/aws_vpc.md.erb +125 -125
  67. data/docs/resources/aws_vpcs.md.erb +125 -125
  68. data/docs/resources/azure_generic_resource.md.erb +171 -171
  69. data/docs/resources/azure_resource_group.md.erb +284 -284
  70. data/docs/resources/azure_virtual_machine.md.erb +347 -347
  71. data/docs/resources/azure_virtual_machine_data_disk.md.erb +224 -224
  72. data/docs/resources/bash.md.erb +75 -75
  73. data/docs/resources/bond.md.erb +90 -90
  74. data/docs/resources/bridge.md.erb +57 -57
  75. data/docs/resources/bsd_service.md.erb +67 -67
  76. data/docs/resources/chocolatey_package.md.erb +58 -58
  77. data/docs/resources/command.md.erb +138 -138
  78. data/docs/resources/cpan.md.erb +79 -79
  79. data/docs/resources/cran.md.erb +64 -64
  80. data/docs/resources/crontab.md.erb +89 -89
  81. data/docs/resources/csv.md.erb +54 -54
  82. data/docs/resources/dh_params.md.erb +205 -205
  83. data/docs/resources/directory.md.erb +30 -30
  84. data/docs/resources/docker.md.erb +219 -219
  85. data/docs/resources/docker_container.md.erb +103 -103
  86. data/docs/resources/docker_image.md.erb +94 -94
  87. data/docs/resources/docker_service.md.erb +114 -114
  88. data/docs/resources/elasticsearch.md.erb +242 -242
  89. data/docs/resources/etc_fstab.md.erb +125 -125
  90. data/docs/resources/etc_group.md.erb +75 -75
  91. data/docs/resources/etc_hosts.md.erb +78 -78
  92. data/docs/resources/etc_hosts_allow.md.erb +74 -74
  93. data/docs/resources/etc_hosts_deny.md.erb +74 -74
  94. data/docs/resources/file.md.erb +526 -526
  95. data/docs/resources/filesystem.md.erb +41 -41
  96. data/docs/resources/firewalld.md.erb +107 -107
  97. data/docs/resources/gem.md.erb +79 -79
  98. data/docs/resources/group.md.erb +61 -61
  99. data/docs/resources/grub_conf.md.erb +101 -101
  100. data/docs/resources/host.md.erb +86 -86
  101. data/docs/resources/http.md.erb +197 -197
  102. data/docs/resources/iis_app.md.erb +122 -122
  103. data/docs/resources/iis_site.md.erb +135 -135
  104. data/docs/resources/inetd_conf.md.erb +94 -94
  105. data/docs/resources/ini.md.erb +76 -76
  106. data/docs/resources/interface.md.erb +58 -58
  107. data/docs/resources/iptables.md.erb +64 -64
  108. data/docs/resources/json.md.erb +63 -63
  109. data/docs/resources/kernel_module.md.erb +120 -120
  110. data/docs/resources/kernel_parameter.md.erb +53 -53
  111. data/docs/resources/key_rsa.md.erb +85 -85
  112. data/docs/resources/launchd_service.md.erb +57 -57
  113. data/docs/resources/limits_conf.md.erb +75 -75
  114. data/docs/resources/login_defs.md.erb +71 -71
  115. data/docs/resources/mount.md.erb +69 -69
  116. data/docs/resources/mssql_session.md.erb +60 -60
  117. data/docs/resources/mysql_conf.md.erb +99 -99
  118. data/docs/resources/mysql_session.md.erb +74 -74
  119. data/docs/resources/nginx.md.erb +79 -79
  120. data/docs/resources/nginx_conf.md.erb +138 -138
  121. data/docs/resources/npm.md.erb +60 -60
  122. data/docs/resources/ntp_conf.md.erb +60 -60
  123. data/docs/resources/oneget.md.erb +53 -53
  124. data/docs/resources/oracledb_session.md.erb +52 -52
  125. data/docs/resources/os.md.erb +141 -141
  126. data/docs/resources/os_env.md.erb +91 -91
  127. data/docs/resources/package.md.erb +120 -120
  128. data/docs/resources/packages.md.erb +67 -67
  129. data/docs/resources/parse_config.md.erb +103 -103
  130. data/docs/resources/parse_config_file.md.erb +138 -138
  131. data/docs/resources/passwd.md.erb +141 -141
  132. data/docs/resources/pip.md.erb +67 -67
  133. data/docs/resources/port.md.erb +137 -137
  134. data/docs/resources/postgres_conf.md.erb +79 -79
  135. data/docs/resources/postgres_hba_conf.md.erb +93 -93
  136. data/docs/resources/postgres_ident_conf.md.erb +76 -76
  137. data/docs/resources/postgres_session.md.erb +69 -69
  138. data/docs/resources/powershell.md.erb +102 -102
  139. data/docs/resources/processes.md.erb +109 -109
  140. data/docs/resources/rabbitmq_config.md.erb +41 -41
  141. data/docs/resources/registry_key.md.erb +158 -158
  142. data/docs/resources/runit_service.md.erb +57 -57
  143. data/docs/resources/security_policy.md.erb +47 -47
  144. data/docs/resources/service.md.erb +121 -121
  145. data/docs/resources/shadow.md.erb +146 -146
  146. data/docs/resources/ssh_config.md.erb +73 -73
  147. data/docs/resources/sshd_config.md.erb +83 -83
  148. data/docs/resources/ssl.md.erb +119 -119
  149. data/docs/resources/sys_info.md.erb +42 -42
  150. data/docs/resources/systemd_service.md.erb +57 -57
  151. data/docs/resources/sysv_service.md.erb +57 -57
  152. data/docs/resources/upstart_service.md.erb +57 -57
  153. data/docs/resources/user.md.erb +140 -140
  154. data/docs/resources/users.md.erb +127 -127
  155. data/docs/resources/vbscript.md.erb +55 -55
  156. data/docs/resources/virtualization.md.erb +57 -57
  157. data/docs/resources/windows_feature.md.erb +47 -47
  158. data/docs/resources/windows_hotfix.md.erb +53 -53
  159. data/docs/resources/windows_task.md.erb +95 -95
  160. data/docs/resources/wmi.md.erb +81 -81
  161. data/docs/resources/x509_certificate.md.erb +151 -151
  162. data/docs/resources/xinetd_conf.md.erb +156 -156
  163. data/docs/resources/xml.md.erb +85 -85
  164. data/docs/resources/yaml.md.erb +69 -69
  165. data/docs/resources/yum.md.erb +98 -98
  166. data/docs/resources/zfs_dataset.md.erb +53 -53
  167. data/docs/resources/zfs_pool.md.erb +47 -47
  168. data/docs/ruby_usage.md +203 -203
  169. data/docs/shared/matcher_be.md.erb +1 -1
  170. data/docs/shared/matcher_cmp.md.erb +43 -43
  171. data/docs/shared/matcher_eq.md.erb +3 -3
  172. data/docs/shared/matcher_include.md.erb +1 -1
  173. data/docs/shared/matcher_match.md.erb +1 -1
  174. data/docs/shell.md +217 -217
  175. data/examples/README.md +8 -8
  176. data/examples/inheritance/README.md +65 -65
  177. data/examples/inheritance/controls/example.rb +14 -14
  178. data/examples/inheritance/inspec.yml +15 -15
  179. data/examples/kitchen-ansible/.kitchen.yml +25 -25
  180. data/examples/kitchen-ansible/Gemfile +19 -19
  181. data/examples/kitchen-ansible/README.md +53 -53
  182. data/examples/kitchen-ansible/files/nginx.repo +6 -6
  183. data/examples/kitchen-ansible/tasks/main.yml +16 -16
  184. data/examples/kitchen-ansible/test/integration/default/default.yml +5 -5
  185. data/examples/kitchen-ansible/test/integration/default/web_spec.rb +28 -28
  186. data/examples/kitchen-chef/.kitchen.yml +20 -20
  187. data/examples/kitchen-chef/Berksfile +3 -3
  188. data/examples/kitchen-chef/Gemfile +19 -19
  189. data/examples/kitchen-chef/README.md +27 -27
  190. data/examples/kitchen-chef/metadata.rb +7 -7
  191. data/examples/kitchen-chef/recipes/default.rb +6 -6
  192. data/examples/kitchen-chef/recipes/nginx.rb +30 -30
  193. data/examples/kitchen-chef/test/integration/default/web_spec.rb +28 -28
  194. data/examples/kitchen-puppet/.kitchen.yml +23 -23
  195. data/examples/kitchen-puppet/Gemfile +20 -20
  196. data/examples/kitchen-puppet/Puppetfile +25 -25
  197. data/examples/kitchen-puppet/README.md +53 -53
  198. data/examples/kitchen-puppet/manifests/site.pp +33 -33
  199. data/examples/kitchen-puppet/metadata.json +11 -11
  200. data/examples/kitchen-puppet/test/integration/default/web_spec.rb +28 -28
  201. data/examples/meta-profile/README.md +37 -37
  202. data/examples/meta-profile/controls/example.rb +13 -13
  203. data/examples/meta-profile/inspec.yml +13 -13
  204. data/examples/profile-attribute.yml +2 -2
  205. data/examples/profile-attribute/README.md +14 -14
  206. data/examples/profile-attribute/controls/example.rb +11 -11
  207. data/examples/profile-attribute/inspec.yml +8 -8
  208. data/examples/profile-aws/controls/iam_password_policy_expiration.rb +8 -8
  209. data/examples/profile-aws/controls/iam_password_policy_max_age.rb +8 -8
  210. data/examples/profile-aws/controls/iam_root_user_mfa.rb +8 -8
  211. data/examples/profile-aws/controls/iam_users_access_key_age.rb +8 -8
  212. data/examples/profile-aws/controls/iam_users_console_users_mfa.rb +8 -8
  213. data/examples/profile-aws/inspec.yml +11 -11
  214. data/examples/profile-azure/controls/azure_resource_group_example.rb +24 -24
  215. data/examples/profile-azure/controls/azure_vm_example.rb +29 -29
  216. data/examples/profile-azure/inspec.yml +11 -11
  217. data/examples/profile-sensitive/README.md +29 -29
  218. data/examples/profile-sensitive/controls/sensitive-failures.rb +9 -9
  219. data/examples/profile-sensitive/controls/sensitive.rb +9 -9
  220. data/examples/profile-sensitive/inspec.yml +8 -8
  221. data/examples/profile/README.md +48 -48
  222. data/examples/profile/controls/example.rb +23 -23
  223. data/examples/profile/controls/gordon.rb +36 -36
  224. data/examples/profile/controls/meta.rb +34 -34
  225. data/examples/profile/inspec.yml +10 -10
  226. data/examples/profile/libraries/gordon_config.rb +59 -59
  227. data/inspec.gemspec +49 -49
  228. data/lib/bundles/README.md +3 -3
  229. data/lib/bundles/inspec-artifact.rb +7 -7
  230. data/lib/bundles/inspec-artifact/README.md +1 -1
  231. data/lib/bundles/inspec-artifact/cli.rb +277 -277
  232. data/lib/bundles/inspec-compliance.rb +16 -16
  233. data/lib/bundles/inspec-compliance/.kitchen.yml +20 -20
  234. data/lib/bundles/inspec-compliance/README.md +193 -193
  235. data/lib/bundles/inspec-compliance/api.rb +360 -360
  236. data/lib/bundles/inspec-compliance/api/login.rb +193 -193
  237. data/lib/bundles/inspec-compliance/bootstrap.sh +41 -41
  238. data/lib/bundles/inspec-compliance/cli.rb +260 -260
  239. data/lib/bundles/inspec-compliance/configuration.rb +103 -103
  240. data/lib/bundles/inspec-compliance/http.rb +125 -125
  241. data/lib/bundles/inspec-compliance/support.rb +36 -36
  242. data/lib/bundles/inspec-compliance/target.rb +112 -112
  243. data/lib/bundles/inspec-compliance/test/integration/default/cli.rb +93 -93
  244. data/lib/bundles/inspec-habitat.rb +12 -12
  245. data/lib/bundles/inspec-habitat/cli.rb +36 -36
  246. data/lib/bundles/inspec-habitat/log.rb +10 -10
  247. data/lib/bundles/inspec-habitat/profile.rb +391 -391
  248. data/lib/bundles/inspec-init.rb +8 -8
  249. data/lib/bundles/inspec-init/README.md +31 -31
  250. data/lib/bundles/inspec-init/cli.rb +97 -97
  251. data/lib/bundles/inspec-init/templates/profile/README.md +3 -3
  252. data/lib/bundles/inspec-init/templates/profile/controls/example.rb +19 -19
  253. data/lib/bundles/inspec-init/templates/profile/inspec.yml +8 -8
  254. data/lib/bundles/inspec-supermarket.rb +13 -13
  255. data/lib/bundles/inspec-supermarket/README.md +45 -45
  256. data/lib/bundles/inspec-supermarket/api.rb +84 -84
  257. data/lib/bundles/inspec-supermarket/cli.rb +73 -73
  258. data/lib/bundles/inspec-supermarket/target.rb +34 -34
  259. data/lib/fetchers/git.rb +163 -163
  260. data/lib/fetchers/local.rb +74 -74
  261. data/lib/fetchers/mock.rb +35 -35
  262. data/lib/fetchers/url.rb +247 -247
  263. data/lib/inspec.rb +24 -24
  264. data/lib/inspec/archive/tar.rb +29 -29
  265. data/lib/inspec/archive/zip.rb +19 -19
  266. data/lib/inspec/backend.rb +93 -93
  267. data/lib/inspec/base_cli.rb +368 -368
  268. data/lib/inspec/cached_fetcher.rb +66 -66
  269. data/lib/inspec/cli.rb +292 -292
  270. data/lib/inspec/completions/bash.sh.erb +45 -45
  271. data/lib/inspec/completions/fish.sh.erb +34 -34
  272. data/lib/inspec/completions/zsh.sh.erb +61 -61
  273. data/lib/inspec/control_eval_context.rb +179 -179
  274. data/lib/inspec/dependencies/cache.rb +72 -72
  275. data/lib/inspec/dependencies/dependency_set.rb +92 -92
  276. data/lib/inspec/dependencies/lockfile.rb +115 -115
  277. data/lib/inspec/dependencies/requirement.rb +123 -123
  278. data/lib/inspec/dependencies/resolver.rb +86 -86
  279. data/lib/inspec/describe.rb +27 -27
  280. data/lib/inspec/dsl.rb +66 -66
  281. data/lib/inspec/dsl_shared.rb +33 -33
  282. data/lib/inspec/env_printer.rb +157 -157
  283. data/lib/inspec/errors.rb +14 -14
  284. data/lib/inspec/exceptions.rb +12 -12
  285. data/lib/inspec/expect.rb +45 -45
  286. data/lib/inspec/fetcher.rb +45 -45
  287. data/lib/inspec/file_provider.rb +275 -275
  288. data/lib/inspec/formatters.rb +3 -3
  289. data/lib/inspec/formatters/base.rb +259 -259
  290. data/lib/inspec/formatters/json_rspec.rb +20 -20
  291. data/lib/inspec/formatters/show_progress.rb +12 -12
  292. data/lib/inspec/library_eval_context.rb +58 -58
  293. data/lib/inspec/log.rb +11 -11
  294. data/lib/inspec/metadata.rb +247 -247
  295. data/lib/inspec/method_source.rb +24 -24
  296. data/lib/inspec/objects.rb +14 -14
  297. data/lib/inspec/objects/attribute.rb +75 -75
  298. data/lib/inspec/objects/control.rb +61 -61
  299. data/lib/inspec/objects/describe.rb +92 -92
  300. data/lib/inspec/objects/each_loop.rb +36 -36
  301. data/lib/inspec/objects/list.rb +15 -15
  302. data/lib/inspec/objects/or_test.rb +40 -40
  303. data/lib/inspec/objects/ruby_helper.rb +15 -15
  304. data/lib/inspec/objects/tag.rb +27 -27
  305. data/lib/inspec/objects/test.rb +87 -87
  306. data/lib/inspec/objects/value.rb +27 -27
  307. data/lib/inspec/plugins.rb +60 -60
  308. data/lib/inspec/plugins/cli.rb +24 -24
  309. data/lib/inspec/plugins/fetcher.rb +86 -86
  310. data/lib/inspec/plugins/resource.rb +135 -135
  311. data/lib/inspec/plugins/secret.rb +15 -15
  312. data/lib/inspec/plugins/source_reader.rb +40 -40
  313. data/lib/inspec/polyfill.rb +12 -12
  314. data/lib/inspec/profile.rb +513 -513
  315. data/lib/inspec/profile_context.rb +208 -208
  316. data/lib/inspec/profile_vendor.rb +66 -66
  317. data/lib/inspec/reporters.rb +60 -60
  318. data/lib/inspec/reporters/automate.rb +76 -76
  319. data/lib/inspec/reporters/base.rb +25 -25
  320. data/lib/inspec/reporters/cli.rb +356 -356
  321. data/lib/inspec/reporters/json.rb +117 -117
  322. data/lib/inspec/reporters/json_min.rb +48 -48
  323. data/lib/inspec/reporters/junit.rb +78 -78
  324. data/lib/inspec/require_loader.rb +33 -33
  325. data/lib/inspec/resource.rb +190 -190
  326. data/lib/inspec/rule.rb +280 -280
  327. data/lib/inspec/runner.rb +345 -345
  328. data/lib/inspec/runner_mock.rb +41 -41
  329. data/lib/inspec/runner_rspec.rb +175 -175
  330. data/lib/inspec/runtime_profile.rb +26 -26
  331. data/lib/inspec/schema.rb +213 -213
  332. data/lib/inspec/secrets.rb +19 -19
  333. data/lib/inspec/secrets/yaml.rb +30 -30
  334. data/lib/inspec/shell.rb +220 -220
  335. data/lib/inspec/shell_detector.rb +90 -90
  336. data/lib/inspec/source_reader.rb +29 -29
  337. data/lib/inspec/version.rb +8 -8
  338. data/lib/matchers/matchers.rb +339 -339
  339. data/lib/resource_support/aws.rb +50 -50
  340. data/lib/resource_support/aws/aws_backend_base.rb +12 -12
  341. data/lib/resource_support/aws/aws_backend_factory_mixin.rb +12 -12
  342. data/lib/resource_support/aws/aws_plural_resource_mixin.rb +21 -21
  343. data/lib/resource_support/aws/aws_resource_mixin.rb +66 -66
  344. data/lib/resource_support/aws/aws_singular_resource_mixin.rb +24 -24
  345. data/lib/resources/aide_conf.rb +151 -151
  346. data/lib/resources/apache.rb +48 -48
  347. data/lib/resources/apache_conf.rb +149 -149
  348. data/lib/resources/apt.rb +149 -149
  349. data/lib/resources/audit_policy.rb +63 -63
  350. data/lib/resources/auditd.rb +231 -231
  351. data/lib/resources/auditd_conf.rb +46 -46
  352. data/lib/resources/aws/aws_cloudtrail_trail.rb +93 -93
  353. data/lib/resources/aws/aws_cloudtrail_trails.rb +47 -47
  354. data/lib/resources/aws/aws_cloudwatch_alarm.rb +62 -62
  355. data/lib/resources/aws/aws_cloudwatch_log_metric_filter.rb +100 -100
  356. data/lib/resources/aws/aws_config_delivery_channel.rb +70 -70
  357. data/lib/resources/aws/aws_config_recorder.rb +93 -93
  358. data/lib/resources/aws/aws_ec2_instance.rb +157 -157
  359. data/lib/resources/aws/aws_ec2_instances.rb +64 -64
  360. data/lib/resources/aws/aws_iam_access_key.rb +106 -106
  361. data/lib/resources/aws/aws_iam_access_keys.rb +149 -149
  362. data/lib/resources/aws/aws_iam_group.rb +58 -58
  363. data/lib/resources/aws/aws_iam_groups.rb +52 -52
  364. data/lib/resources/aws/aws_iam_password_policy.rb +116 -116
  365. data/lib/resources/aws/aws_iam_policies.rb +53 -53
  366. data/lib/resources/aws/aws_iam_policy.rb +291 -291
  367. data/lib/resources/aws/aws_iam_role.rb +55 -55
  368. data/lib/resources/aws/aws_iam_root_user.rb +78 -78
  369. data/lib/resources/aws/aws_iam_user.rb +142 -142
  370. data/lib/resources/aws/aws_iam_users.rb +146 -146
  371. data/lib/resources/aws/aws_kms_key.rb +96 -96
  372. data/lib/resources/aws/aws_kms_keys.rb +53 -53
  373. data/lib/resources/aws/aws_rds_instance.rb +71 -71
  374. data/lib/resources/aws/aws_route_table.rb +63 -63
  375. data/lib/resources/aws/aws_route_tables.rb +60 -60
  376. data/lib/resources/aws/aws_s3_bucket.rb +137 -137
  377. data/lib/resources/aws/aws_s3_bucket_object.rb +82 -82
  378. data/lib/resources/aws/aws_s3_buckets.rb +51 -51
  379. data/lib/resources/aws/aws_security_group.rb +249 -249
  380. data/lib/resources/aws/aws_security_groups.rb +68 -68
  381. data/lib/resources/aws/aws_sns_subscription.rb +78 -78
  382. data/lib/resources/aws/aws_sns_topic.rb +53 -53
  383. data/lib/resources/aws/aws_sns_topics.rb +56 -56
  384. data/lib/resources/aws/aws_subnet.rb +88 -88
  385. data/lib/resources/aws/aws_subnets.rb +53 -53
  386. data/lib/resources/aws/aws_vpc.rb +73 -73
  387. data/lib/resources/aws/aws_vpcs.rb +52 -52
  388. data/lib/resources/azure/azure_backend.rb +377 -377
  389. data/lib/resources/azure/azure_generic_resource.rb +59 -59
  390. data/lib/resources/azure/azure_resource_group.rb +152 -152
  391. data/lib/resources/azure/azure_virtual_machine.rb +264 -264
  392. data/lib/resources/azure/azure_virtual_machine_data_disk.rb +134 -134
  393. data/lib/resources/bash.rb +35 -35
  394. data/lib/resources/bond.rb +69 -69
  395. data/lib/resources/bridge.rb +122 -122
  396. data/lib/resources/chocolatey_package.rb +78 -78
  397. data/lib/resources/command.rb +73 -73
  398. data/lib/resources/cpan.rb +58 -58
  399. data/lib/resources/cran.rb +64 -64
  400. data/lib/resources/crontab.rb +169 -169
  401. data/lib/resources/csv.rb +56 -56
  402. data/lib/resources/dh_params.rb +77 -77
  403. data/lib/resources/directory.rb +25 -25
  404. data/lib/resources/docker.rb +236 -236
  405. data/lib/resources/docker_container.rb +89 -89
  406. data/lib/resources/docker_image.rb +83 -83
  407. data/lib/resources/docker_object.rb +57 -57
  408. data/lib/resources/docker_service.rb +90 -90
  409. data/lib/resources/elasticsearch.rb +169 -169
  410. data/lib/resources/etc_fstab.rb +94 -94
  411. data/lib/resources/etc_group.rb +154 -154
  412. data/lib/resources/etc_hosts.rb +66 -66
  413. data/lib/resources/etc_hosts_allow_deny.rb +112 -112
  414. data/lib/resources/file.rb +298 -298
  415. data/lib/resources/filesystem.rb +31 -31
  416. data/lib/resources/firewalld.rb +143 -143
  417. data/lib/resources/gem.rb +70 -70
  418. data/lib/resources/groups.rb +215 -215
  419. data/lib/resources/grub_conf.rb +227 -227
  420. data/lib/resources/host.rb +306 -306
  421. data/lib/resources/http.rb +253 -253
  422. data/lib/resources/iis_app.rb +101 -101
  423. data/lib/resources/iis_site.rb +148 -148
  424. data/lib/resources/inetd_conf.rb +54 -54
  425. data/lib/resources/ini.rb +29 -29
  426. data/lib/resources/interface.rb +129 -129
  427. data/lib/resources/iptables.rb +80 -80
  428. data/lib/resources/json.rb +111 -111
  429. data/lib/resources/kernel_module.rb +107 -107
  430. data/lib/resources/kernel_parameter.rb +58 -58
  431. data/lib/resources/key_rsa.rb +63 -63
  432. data/lib/resources/limits_conf.rb +46 -46
  433. data/lib/resources/login_def.rb +57 -57
  434. data/lib/resources/mount.rb +88 -88
  435. data/lib/resources/mssql_session.rb +101 -101
  436. data/lib/resources/mysql.rb +82 -82
  437. data/lib/resources/mysql_conf.rb +127 -127
  438. data/lib/resources/mysql_session.rb +85 -85
  439. data/lib/resources/nginx.rb +96 -96
  440. data/lib/resources/nginx_conf.rb +226 -226
  441. data/lib/resources/npm.rb +48 -48
  442. data/lib/resources/ntp_conf.rb +51 -51
  443. data/lib/resources/oneget.rb +71 -71
  444. data/lib/resources/oracledb_session.rb +139 -139
  445. data/lib/resources/os.rb +36 -36
  446. data/lib/resources/os_env.rb +86 -86
  447. data/lib/resources/package.rb +370 -370
  448. data/lib/resources/packages.rb +111 -111
  449. data/lib/resources/parse_config.rb +112 -112
  450. data/lib/resources/passwd.rb +76 -76
  451. data/lib/resources/pip.rb +130 -130
  452. data/lib/resources/platform.rb +109 -109
  453. data/lib/resources/port.rb +771 -771
  454. data/lib/resources/postgres.rb +131 -131
  455. data/lib/resources/postgres_conf.rb +114 -114
  456. data/lib/resources/postgres_hba_conf.rb +90 -90
  457. data/lib/resources/postgres_ident_conf.rb +79 -79
  458. data/lib/resources/postgres_session.rb +71 -71
  459. data/lib/resources/powershell.rb +67 -67
  460. data/lib/resources/processes.rb +204 -204
  461. data/lib/resources/rabbitmq_conf.rb +51 -51
  462. data/lib/resources/registry_key.rb +297 -297
  463. data/lib/resources/security_policy.rb +180 -180
  464. data/lib/resources/service.rb +794 -794
  465. data/lib/resources/shadow.rb +159 -159
  466. data/lib/resources/ssh_conf.rb +97 -97
  467. data/lib/resources/ssl.rb +99 -99
  468. data/lib/resources/sys_info.rb +28 -28
  469. data/lib/resources/toml.rb +32 -32
  470. data/lib/resources/users.rb +654 -654
  471. data/lib/resources/vbscript.rb +68 -68
  472. data/lib/resources/virtualization.rb +247 -247
  473. data/lib/resources/windows_feature.rb +84 -84
  474. data/lib/resources/windows_hotfix.rb +35 -35
  475. data/lib/resources/windows_task.rb +102 -102
  476. data/lib/resources/wmi.rb +110 -110
  477. data/lib/resources/x509_certificate.rb +137 -137
  478. data/lib/resources/xinetd.rb +106 -106
  479. data/lib/resources/xml.rb +46 -46
  480. data/lib/resources/yaml.rb +43 -43
  481. data/lib/resources/yum.rb +180 -180
  482. data/lib/resources/zfs_dataset.rb +60 -60
  483. data/lib/resources/zfs_pool.rb +49 -49
  484. data/lib/source_readers/flat.rb +39 -39
  485. data/lib/source_readers/inspec.rb +75 -75
  486. data/lib/utils/command_wrapper.rb +27 -27
  487. data/lib/utils/convert.rb +12 -12
  488. data/lib/utils/database_helpers.rb +77 -77
  489. data/lib/utils/enumerable_delegation.rb +9 -9
  490. data/lib/utils/erlang_parser.rb +192 -192
  491. data/lib/utils/file_reader.rb +25 -25
  492. data/lib/utils/filter.rb +273 -273
  493. data/lib/utils/filter_array.rb +27 -27
  494. data/lib/utils/find_files.rb +47 -47
  495. data/lib/utils/hash.rb +41 -41
  496. data/lib/utils/json_log.rb +18 -18
  497. data/lib/utils/latest_version.rb +22 -22
  498. data/lib/utils/modulator.rb +12 -12
  499. data/lib/utils/nginx_parser.rb +105 -105
  500. data/lib/utils/object_traversal.rb +49 -49
  501. data/lib/utils/parser.rb +274 -274
  502. data/lib/utils/pkey_reader.rb +15 -15
  503. data/lib/utils/plugin_registry.rb +93 -93
  504. data/lib/utils/simpleconfig.rb +120 -120
  505. data/lib/utils/spdx.rb +13 -13
  506. data/lib/utils/spdx.txt +343 -343
  507. metadata +3 -3
@@ -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