inspec 2.0.32 → 2.0.45

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